From 66ff71ca554c878c3a5901b4a47805eb50ef4bb0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 Jun 2017 00:50:51 +0200 Subject: [PATCH] Applied the latest mainline PCem commits. --- src/CPU/codegen_timing_pentium.c | 185 +++++++++++++++++++++++++------ src/SOUND/snd_gus.c | 60 ++++++---- src/dma.c | 3 +- 3 files changed, 197 insertions(+), 51 deletions(-) diff --git a/src/CPU/codegen_timing_pentium.c b/src/CPU/codegen_timing_pentium.c index e5e4ed13d..9533027f4 100644 --- a/src/CPU/codegen_timing_pentium.c +++ b/src/CPU/codegen_timing_pentium.c @@ -42,6 +42,11 @@ static int pair_timings[4][4] = #define CYCLES_RMW (2 << 0) #define CYCLES_BRANCH (3 << 0) +/*Instruction has immediate data. Can only be used with PAIR_U/PAIR_V/PAIR_UV*/ +#define CYCLES_HASIMM (3 << 2) +#define CYCLES_IMM8 (1 << 2) +#define CYCLES_IMM1632 (2 << 2) + #define CYCLES_MASK ((1 << 7) - 1) /*Instruction is MMX shift or pack/unpack instruction*/ @@ -62,6 +67,8 @@ static int pair_timings[4][4] = /*Instruction is FXCH and only pairs in V pipe with FX pairable instruction*/ #define PAIR_FXCH (6 << 29) +#define PAIR_FPU (4 << 29) + #define PAIR_MASK (7 << 29) /*Instruction has input dependency on register in REG field*/ @@ -296,38 +303,38 @@ static uint32_t opcode_timings_mod3[256] = /* ADD ADD ADD ADD*/ /*00*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, /* ADD ADD PUSH ES POP ES*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), /* OR OR OR OR*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, /* OR OR PUSH CS */ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_NP | CYCLES(1), INVALID, + PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), INVALID, /* ADC ADC ADC ADC*/ /*10*/ PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, /* ADC ADC PUSH SS POP SS*/ - PAIR_U | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), + PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), /* SBB SBB SBB SBB*/ PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, /* SBB SBB PUSH DS POP DS*/ - PAIR_U | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), + PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), /* AND AND AND AND*/ /*20*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, /* AND AND DAA*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), /* SUB SUB SUB SUB*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, /* SUB SUB DAS*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), /* XOR XOR XOR XOR*/ /*30*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, /* XOR XOR AAA*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), /* CMP CMP CMP CMP*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_RM | SRCDEP_REG, /* CMP CMP AAS*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_EAX, INVALID, PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, INVALID, PAIR_NP | CYCLES(3), /* INC EAX INC ECX INC EDX INC EBX*/ /*40*/ PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, @@ -810,14 +817,20 @@ static uint32_t opcode_timings_df_mod3[8] = PAIR_NP | CYCLES(2), INVALID, INVALID, INVALID }; +static uint32_t opcode_timings_81[8] = +{ + PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, + PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RM | SRCDEP_REG | CYCLES_IMM1632 +}; static uint32_t opcode_timings_8x[8] = { - PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, - PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG + PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, + PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RM | SRCDEP_REG | CYCLES_IMM8 }; static int decode_delay; static uint8_t last_prefix; +static int prefixes; static inline int COUNT(uint32_t c, int op_32) { @@ -831,6 +844,10 @@ static inline int COUNT(uint32_t c, int op_32) return c & 0xffff; if ((c & PAIR_MASK) == PAIR_FX) return c & 0xffff; + if ((c & PAIR_MASK) == PAIR_FXCH) + return c & 0xffff; + if ((c & PAIR_UV) && !(c & PAIR_FPU)) + c &= 3; switch (c & CYCLES_MASK) { case CYCLES_REG: @@ -848,6 +865,80 @@ static inline int COUNT(uint32_t c, int op_32) return c; } +static inline int codegen_timing_has_displacement(uint32_t fetchdat, int op_32) +{ + if (op_32 & 0x200) + { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) + { + /*Has SIB*/ + if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0x700) == 0x500) + return 1; + } + else + { + if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0xc7) == 0x05) + return 1; + } + } + else + { + if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0xc7) == 0x06) + return 1; + } + return 0; +} + +/*The instruction is only of interest here if it's longer than 7 bytes, as that's the + limit on Pentium MMX parallel decoding*/ +static inline int codegen_timing_instr_length(uint32_t timing, uint32_t fetchdat, int op_32) +{ + int len = prefixes; + if ((timing & CYCLES_MASK) == CYCLES_RM || (timing & CYCLES_MASK) == CYCLES_RMW) + { + len += 2; /*Opcode + ModR/M*/ + if ((timing & CYCLES_HASIMM) == CYCLES_IMM8) + len++; + if ((timing & CYCLES_HASIMM) == CYCLES_IMM1632) + len += (op_32 & 0x100) ? 4 : 2; + + if (op_32 & 0x200) + { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) + { + /* Has SIB*/ + len++; + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0x700) == 0x500) + len += 4; + } + else + { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0xc7) == 0x05) + len += 4; + } + } + else + { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 2; + else if ((fetchdat & 0xc7) == 0x06) + len += 2; + } + } + + return len; +} + void codegen_timing_pentium_block_start() { u_pipe_full = decode_delay = 0; @@ -856,10 +947,12 @@ void codegen_timing_pentium_block_start() void codegen_timing_pentium_start() { last_prefix = 0; + prefixes = 0; } void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) { + prefixes++; if (cpu_hasMMX && prefix == 0x0f) { /*On Pentium MMX 0fh prefix is 'free'*/ @@ -933,11 +1026,16 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) default: switch (opcode) { - case 0x80: case 0x81: case 0x82: case 0x83: + case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_mod3 : opcode_timings_8x; if (!mod3) opcode = (fetchdat >> 3) & 7; break; + case 0x81: + timings = mod3 ? opcode_timings_mod3 : opcode_timings_81; + if (!mod3) + opcode = (fetchdat >> 3) & 7; + break; case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; @@ -980,23 +1078,38 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if ((timings[opcode] & PAIR_V) && !(u_pipe_regmask & regmask) && !decode_delay) { - int t1 = u_pipe_timings[u_pipe_opcode] & CYCLES_MASK; - int t2 = timings[opcode] & CYCLES_MASK; - int t_pair; + int has_displacement; - if (t1 < 0 || t2 < 0 || t1 > CYCLES_BRANCH || t2 > CYCLES_BRANCH) - fatal("Pair out of range\n"); + if (timings[opcode] & CYCLES_HASIMM) + has_displacement = codegen_timing_has_displacement(fetchdat, op_32); + else + has_displacement = 0; + + if (!has_displacement && (!cpu_hasMMX || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) + { + int t1 = u_pipe_timings[u_pipe_opcode] & CYCLES_MASK; + int t2 = timings[opcode] & CYCLES_MASK; + int t_pair; - t_pair = pair_timings[t1][t2]; - if (t_pair < 1) - fatal("Illegal pair timings : t1=%i t2=%i u_opcode=%02x v_opcode=%02x\n", t1, t2, u_pipe_opcode, opcode); + if (!(u_pipe_timings[u_pipe_opcode] & PAIR_FPU)) + t1 &= 3; + if (!(timings[opcode] & PAIR_FPU)) + t2 &= 3; + + if (t1 < 0 || t2 < 0 || t1 > CYCLES_BRANCH || t2 > CYCLES_BRANCH) + fatal("Pair out of range\n"); + + t_pair = pair_timings[t1][t2]; + if (t_pair < 1) + fatal("Illegal pair timings : t1=%i t2=%i u_opcode=%02x v_opcode=%02x\n", t1, t2, u_pipe_opcode, opcode); - codegen_block_cycles += t_pair; - decode_delay = (-t_pair) + 1; + codegen_block_cycles += t_pair; + decode_delay = (-t_pair) + 1; - /*Instruction can pair with previous*/ - u_pipe_full = 0; - return; + /*Instruction can pair with previous*/ + u_pipe_full = 0; + return; + } } nopair: /*Instruction can not pair with previous*/ @@ -1008,13 +1121,23 @@ nopair: if ((timings[opcode] & PAIR_U) && !decode_delay) { - /*Instruction might pair with next*/ - u_pipe_full = 1; - u_pipe_opcode = opcode; - u_pipe_timings = timings; - u_pipe_op_32 = op_32; - u_pipe_regmask = get_dstdep_mask(timings[opcode], fetchdat, bit8); - return; + int has_displacement; + + if (timings[opcode] & CYCLES_HASIMM) + has_displacement = codegen_timing_has_displacement(fetchdat, op_32); + else + has_displacement = 0; + + if ((!has_displacement || cpu_hasMMX) && (!cpu_hasMMX || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) + { + /*Instruction might pair with next*/ + u_pipe_full = 1; + u_pipe_opcode = opcode; + u_pipe_timings = timings; + u_pipe_op_32 = op_32; + u_pipe_regmask = get_dstdep_mask(timings[opcode], fetchdat, bit8); + return; + } } /*Instruction can not pair and must run now*/ diff --git a/src/SOUND/snd_gus.c b/src/SOUND/snd_gus.c index bf625dfb2..3981b4960 100644 --- a/src/SOUND/snd_gus.c +++ b/src/SOUND/snd_gus.c @@ -2,14 +2,14 @@ #include #include #include "../ibm.h" + +#include "../device.h" +#include "../dma.h" #include "../io.h" #include "../pic.h" -#include "../dma.h" -#include "../timer.h" -#include "../device.h" #include "sound.h" #include "snd_gus.h" - +#include "../timer.h" typedef struct gus_t { @@ -235,7 +235,7 @@ void writegus(uint16_t addr, uint8_t val, void *p) case 0xA: /*Current addr high*/ gus->cur[gus->voice]=(gus->cur[gus->voice]&0x1F00FFFF)|(val<<16); -gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); + gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); break; case 0xB: /*Current addr low*/ gus->cur[gus->voice]=(gus->cur[gus->voice]&0x1FFFFF00)|val; @@ -257,10 +257,6 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); switch (gus->global) { case 0: /*Voice control*/ - if (!(val&1) && gus->ctrl[gus->voice]&1) - { - } - gus->ctrl[gus->voice] = val & 0x7f; old = gus->waveirqs[gus->voice]; @@ -307,7 +303,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); break; case 0xB: /*Current addr low*/ gus->cur[gus->voice]=(gus->cur[gus->voice]&0x1FFF00FF)|(val<<8); -gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); + gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); break; case 0xC: /*Pan*/ gus->pan_l[gus->voice] = 15 - (val & 0xf); @@ -341,13 +337,27 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); while (c<65536) { int dma_result; - d = gus->ram[gus->dmaaddr]; - if (val & 0x80) d ^= 0x80; - dma_result = dma_channel_write(gus->dma, d); - if (dma_result == DMA_NODATA) - break; + if (val & 0x04) + { + uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1); + d = gus->ram[gus_addr] | (gus->ram[gus_addr + 1] << 8); + if (val & 0x80) + d ^= 0x8080; + dma_result = dma_channel_write(gus->dma, d); + if (dma_result == DMA_NODATA) + break; + } + else + { + d = gus->ram[gus->dmaaddr]; + if (val & 0x80) + d ^= 0x80; + dma_result = dma_channel_write(gus->dma, d); + if (dma_result == DMA_NODATA) + break; + } gus->dmaaddr++; - gus->dmaaddr&=0xFFFFF; + gus->dmaaddr &= 0xFFFFF; c++; if (dma_result & DMA_OVER) break; @@ -363,10 +373,22 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); d = dma_channel_read(gus->dma); if (d == DMA_NODATA) break; - if (val&0x80) d^=0x80; - gus->ram[gus->dmaaddr]=d; + if (val & 0x04) + { + uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1); + if (val & 0x80) + d ^= 0x8080; + gus->ram[gus_addr] = d & 0xff; + gus->ram[gus_addr +1] = (d >> 8) & 0xff; + } + else + { + if (val & 0x80) + d ^= 0x80; + gus->ram[gus->dmaaddr] = d; + } gus->dmaaddr++; - gus->dmaaddr&=0xFFFFF; + gus->dmaaddr &= 0xFFFFF; c++; if (d & DMA_OVER) break; diff --git a/src/dma.c b/src/dma.c index 96f98bd96..ae95ffafa 100644 --- a/src/dma.c +++ b/src/dma.c @@ -705,11 +705,12 @@ int dma_channel_write(int channel, uint16_t val) dma16.cc[channel] = dma16.cb[channel] + 1; dma16.ac[channel] = dma16.ab[channel]; } + else dma16.m |= (1 << channel); dma16.stat |= (1 << channel); } - if (dma.m & (1 << channel)) + if (dma16.m & (1 << channel)) return DMA_OVER; } return 0;