h8_dma: Preliminary support for short address mode

This commit is contained in:
AJR 2020-11-17 21:51:06 -05:00
parent 8571bab3b5
commit 7b657d9b61
4 changed files with 168 additions and 31 deletions

View File

@ -40,22 +40,25 @@ void h83002_device::map(address_map &map)
map(base | 0xfd10, base | 0xff0f).ram();
// DMA: only full address mode supported
map(base | 0xff20, base | 0xff21).rw("dma:0", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w));
map(base | 0xff22, base | 0xff23).rw("dma:0", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w));
map(base | 0xff24, base | 0xff25).rw("dma:0", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w));
map(base | 0xff26, base | 0xff26).rw("dma:0", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w));
map(base | 0xff27, base | 0xff27).rw("dma:0", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w));
map(base | 0xff28, base | 0xff29).rw("dma:0", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w));
map(base | 0xff2a, base | 0xff2b).rw("dma:0", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w));
map(base | 0xff2c, base | 0xff2d).rw("dma:0", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w));
map(base | 0xff2e, base | 0xff2e).rw("dma:0", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w));
map(base | 0xff2f, base | 0xff2f).rw("dma:0", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w));
map(base | 0xff30, base | 0xff31).rw("dma:1", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w));
map(base | 0xff32, base | 0xff33).rw("dma:1", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w));
map(base | 0xff34, base | 0xff35).rw("dma:1", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w));
map(base | 0xff36, base | 0xff36).rw("dma:1", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w));
map(base | 0xff37, base | 0xff37).rw("dma:1", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w));
map(base | 0xff38, base | 0xff39).rw("dma:1", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w));
map(base | 0xff3a, base | 0xff3b).rw("dma:1", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w));
map(base | 0xff3c, base | 0xff3d).rw("dma:1", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w));
map(base | 0xff3e, base | 0xff3e).rw("dma:1", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w));
map(base | 0xff3f, base | 0xff3f).rw("dma:1", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w));
map(base | 0xff60, base | 0xff60).rw("timer16", FUNC(h8_timer16_device::tstr_r), FUNC(h8_timer16_device::tstr_w));

View File

@ -41,34 +41,40 @@ void h83003_device::map(address_map &map)
map(base | 0xfd10, base | 0xff0f).ram();
// DMA: only full address mode supported
map(base | 0xff20, base | 0xff21).rw("dma:0", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w));
map(base | 0xff22, base | 0xff23).rw("dma:0", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w));
map(base | 0xff24, base | 0xff25).rw("dma:0", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w));
map(base | 0xff26, base | 0xff26).rw("dma:0", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w));
map(base | 0xff27, base | 0xff27).rw("dma:0", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w));
map(base | 0xff28, base | 0xff29).rw("dma:0", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w));
map(base | 0xff2a, base | 0xff2b).rw("dma:0", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w));
map(base | 0xff2c, base | 0xff2d).rw("dma:0", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w));
map(base | 0xff2e, base | 0xff2e).rw("dma:0", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w));
map(base | 0xff2f, base | 0xff2f).rw("dma:0", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w));
map(base | 0xff30, base | 0xff31).rw("dma:1", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w));
map(base | 0xff32, base | 0xff33).rw("dma:1", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w));
map(base | 0xff34, base | 0xff35).rw("dma:1", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w));
map(base | 0xff36, base | 0xff36).rw("dma:1", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w));
map(base | 0xff37, base | 0xff37).rw("dma:1", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w));
map(base | 0xff38, base | 0xff39).rw("dma:1", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w));
map(base | 0xff3a, base | 0xff3b).rw("dma:1", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w));
map(base | 0xff3c, base | 0xff3d).rw("dma:1", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w));
map(base | 0xff3e, base | 0xff3e).rw("dma:1", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w));
map(base | 0xff3f, base | 0xff3f).rw("dma:1", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w));
map(base | 0xff40, base | 0xff41).rw("dma:2", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w));
map(base | 0xff42, base | 0xff43).rw("dma:2", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w));
map(base | 0xff44, base | 0xff45).rw("dma:2", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w));
map(base | 0xff46, base | 0xff46).rw("dma:2", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w));
map(base | 0xff47, base | 0xff47).rw("dma:2", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w));
map(base | 0xff48, base | 0xff49).rw("dma:2", FUNC(h8_dma_channel_device::marbh_r), FUNC(h8_dma_channel_device::marbh_w));
map(base | 0xff4a, base | 0xff4b).rw("dma:2", FUNC(h8_dma_channel_device::marbl_r), FUNC(h8_dma_channel_device::marbl_w));
map(base | 0xff4c, base | 0xff4d).rw("dma:2", FUNC(h8_dma_channel_device::etcrb_r), FUNC(h8_dma_channel_device::etcrb_w));
map(base | 0xff4e, base | 0xff4e).rw("dma:2", FUNC(h8_dma_channel_device::ioarb8_r), FUNC(h8_dma_channel_device::ioarb8_w));
map(base | 0xff4f, base | 0xff4f).rw("dma:2", FUNC(h8_dma_channel_device::dtcrb_r), FUNC(h8_dma_channel_device::dtcrb_w));
map(base | 0xff50, base | 0xff51).rw("dma:3", FUNC(h8_dma_channel_device::marah_r), FUNC(h8_dma_channel_device::marah_w));
map(base | 0xff52, base | 0xff53).rw("dma:3", FUNC(h8_dma_channel_device::maral_r), FUNC(h8_dma_channel_device::maral_w));
map(base | 0xff54, base | 0xff55).rw("dma:3", FUNC(h8_dma_channel_device::etcra_r), FUNC(h8_dma_channel_device::etcra_w));
map(base | 0xff56, base | 0xff56).rw("dma:3", FUNC(h8_dma_channel_device::ioara8_r), FUNC(h8_dma_channel_device::ioara8_w));
map(base | 0xff57, base | 0xff57).rw("dma:3", FUNC(h8_dma_channel_device::dtcra_r), FUNC(h8_dma_channel_device::dtcra_w));
map(base | 0xff60, base | 0xff60).rw("timer16", FUNC(h8_timer16_device::tstr_r), FUNC(h8_timer16_device::tstr_w));

View File

@ -15,6 +15,10 @@ void h8_dma_device::device_start()
{
dmach0->set_id(0<<1);
dmach1->set_id(1<<1);
save_item(NAME(dmabcr));
save_item(NAME(dmawer));
save_item(NAME(dreq));
}
void h8_dma_device::device_reset()
@ -146,6 +150,25 @@ void h8_dma_channel_device::set_info(const char *_intc, int _irq_base, int v0, i
void h8_dma_channel_device::device_start()
{
save_item(STRUCT_MEMBER(state, source));
save_item(STRUCT_MEMBER(state, dest));
save_item(STRUCT_MEMBER(state, incs));
save_item(STRUCT_MEMBER(state, incd));
save_item(STRUCT_MEMBER(state, count));
save_item(STRUCT_MEMBER(state, id));
save_item(STRUCT_MEMBER(state, autoreq));
save_item(STRUCT_MEMBER(state, suspended));
save_item(STRUCT_MEMBER(state, mode_16));
save_item(NAME(mar));
save_item(NAME(ioar));
save_item(NAME(etcr));
save_item(NAME(dmacr));
save_item(NAME(dtcr));
save_item(NAME(dta));
save_item(NAME(dte));
save_item(NAME(dtie));
save_item(NAME(fae));
save_item(NAME(sae));
}
void h8_dma_channel_device::device_reset()
@ -192,16 +215,26 @@ void h8_dma_channel_device::maral_w(offs_t offset, uint16_t data, uint16_t mem_m
uint16_t h8_dma_channel_device::ioara_r()
{
logerror("iorar_r %04x\n", ioar[0]);
return ioar[0];
}
uint8_t h8_dma_channel_device::ioara8_r()
{
return ioar[0] & 0x00ff;
}
void h8_dma_channel_device::ioara_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&ioar[0]);
logerror("ioara_w %04x\n", ioar[0]);
}
void h8_dma_channel_device::ioara8_w(uint8_t data)
{
ioar[0] = data | 0xff00;
logerror("ioara_w %04x\n", ioar[0]);
}
uint16_t h8_dma_channel_device::etcra_r()
{
logerror("etcra_r %04x\n", etcr[0]);
@ -241,16 +274,26 @@ void h8_dma_channel_device::marbl_w(offs_t offset, uint16_t data, uint16_t mem_m
uint16_t h8_dma_channel_device::ioarb_r()
{
logerror("ioarb_r %04x\n", ioar[1]);
return ioar[1];
}
uint8_t h8_dma_channel_device::ioarb8_r()
{
return ioar[1] & 0x00ff;
}
void h8_dma_channel_device::ioarb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&ioar[1]);
logerror("ioarb_w %04x\n", ioar[1]);
}
void h8_dma_channel_device::ioarb8_w(uint8_t data)
{
ioar[1] = data | 0xff00;
logerror("ioarb_w %04x\n", ioar[1]);
}
uint16_t h8_dma_channel_device::etcrb_r()
{
logerror("etcrb_r %04x\n", etcr[1]);
@ -312,35 +355,60 @@ void h8_dma_channel_device::h8h_sync()
// update DMACR
dmacr = 0;
if(BIT(dtcr[0], 6)) dmacr |= 1 << 15; // DTSZ
dmacr |= ((dtcr[0] & 0b110000) >> 4) << 13; // SAID, SAIDE
if(BIT(dtcr[0], 0)) dmacr |= 1 << 11; // BLKE
if(BIT(dtcr[1], 3)) dmacr |= 1 << 12; // BLKDIR (TMS)
dmacr |= ((dtcr[1] & 0b110000) >> 4) << 5; // DAID, DAIDE
if(BIT(dmacr, 11)) {
// Block Transfer Mode
switch(dtcr[1] & 0b111) { // DTS
case 0b000: dmacr |= 0b1000; break; // ITU channel 0
case 0b001: dmacr |= 0b1001; break; // ITU channel 1
case 0b010: dmacr |= 0b1010; break; // ITU channel 2
case 0b011: dmacr |= 0b1011; break; // ITU channel 3
case 0b110: dmacr |= 0b1000; break; // DREQ falling edge
dmacr |= ((dtcr[0] & 0b110000) >> 4) << 13; // SAID/DTID, SAIDE/RPE
dmacr |= ((dtcr[1] & 0b110000) >> 4) << 5; // DAID/DTID, DAIDE/RPE
uint8_t _dte = 0;
if(BIT(dtcr[0], 7)) _dte |= 0b01; // DTE
if(BIT(dtcr[1], 7)) _dte |= 0b10; // DTME/DTE
bool _fae = (dtcr[0] & 0b110) == 0b110; // A channel operates in full address mode when DTS2A and DTS1A are both set to 1.
bool _sae = false; // don't support
uint8_t _dta = 0; // don't support
uint8_t _dtie = 0;
if(_fae) {
// Full address mode
if(BIT(dtcr[0], 3)) _dtie = 0b11;
if(BIT(dtcr[0], 0)) {
// Block Transfer Mode
dmacr |= 1 << 11; // BLKE
if(BIT(dtcr[1], 3)) dmacr |= 1 << 12; // BLKDIR (TMS)
switch(dtcr[1] & 0b111) { // DTP (DTS)
case 0b000: dmacr |= 0b1000; break; // ITU channel 0
case 0b001: dmacr |= 0b1001; break; // ITU channel 1
case 0b010: dmacr |= 0b1010; break; // ITU channel 2
case 0b011: dmacr |= 0b1011; break; // ITU channel 3
case 0b110: dmacr |= 0b1000; break; // DREQ falling edge
}
} else {
// Normal Mode
switch(dtcr[1] & 0b111) { // DTP (DTS)
case 0b000: dmacr |= 0b0111; break; // Auto-request (burst mode)
case 0b010: dmacr |= 0b0110; break; // Auto-request (cycle-steal mode)
case 0b110: dmacr |= 0b0010; break; // DREQ falling edge
case 0b111: dmacr |= 0b0011; break; // DREQ low-level
}
}
} else {
// Normal Mode
switch(dtcr[1] & 0b111) { // DTS
case 0b000: dmacr |= 0b0111; break; // Auto-request (burst mode)
case 0b010: dmacr |= 0b0110; break; // Auto-request (cycle-steal mode)
case 0b110: dmacr |= 0b0010; break; // DREQ falling edge
case 0b111: dmacr |= 0b0011; break; // DREQ low-level
// Short address mode
if(BIT(dtcr[0], 3)) _dtie |= 0b01;
if(BIT(dtcr[1], 3)) _dtie |= 0b10;
for(int submodule = 0; submodule < 2; submodule++) {
switch(dtcr[submodule] & 0b111) { // DTP, DTDIR (DTS)
case 0b000: dmacr |= 0b01000 << (submodule ? 0 : 8); break; // ITU channel 0
case 0b001: dmacr |= 0b01001 << (submodule ? 0 : 8); break; // ITU channel 1
case 0b010: dmacr |= 0b01010 << (submodule ? 0 : 8); break; // ITU channel 2
case 0b011: dmacr |= 0b01011 << (submodule ? 0 : 8); break; // ITU channel 3
//case 0b011: dmacr |= 0b10001 << (submodule ? 0 : 8); break; // A/D converter conversion end (H8/3006)
case 0b100: dmacr |= 0b00100 << (submodule ? 0 : 8); break; // SCI channel 0 transmission data empty
case 0b101: dmacr |= 0b10101 << (submodule ? 0 : 8); break; // SCI channel 0 receive data full
case 0b110: dmacr |= 0b00010 << (submodule ? 0 : 8); break; // DREQ falling edge (B only)
case 0b111: dmacr |= 0b00011 << (submodule ? 0 : 8); break; // DREQ low-level (B only)
}
}
}
// set_bcr
bool _fae = (dtcr[0] & 0b110) == 0b110; // A channel operates in full address mode when DTS2A and DTS1A are both set to 1.
uint8_t _dta = 0; // don't support
uint8_t _dte = BIT(dtcr[0], 7) ? 0b11 : 0b00;
uint8_t _dtie = BIT(dtcr[0], 3) ? 0b11 : 0b00;
set_bcr(_fae, !_fae, _dta, _dte, _dtie);
set_bcr(_fae, _sae, _dta, _dte, _dtie);
start_test(-1);
}
@ -382,7 +450,21 @@ bool h8_dma_channel_device::start_test(int vector)
if(dte == 0)
return false;
throw emu_fatalerror("%s: DMA startup test in short address mode unimplemented.\n", tag());
if(vector == -1) {
// A has priority over B
if(dte & 2)
start(1);
if(dte & 1)
start(0);
return true;
} else if(dte & 2) {
// DREQ trigger (B only)
if(((dmacr & 0b111) == 0b0010 && vector == DREQ_EDGE) || ((dmacr & 0b111) == 0b0011 && vector == DREQ_LEVEL)) {
state[1].suspended = false;
return true;
}
}
return false;
}
}
@ -404,7 +486,35 @@ void h8_dma_channel_device::start(int submodule)
cpu->set_current_dma(state + submodule);
}
} else {
throw emu_fatalerror("%s: DMA start in short address mode unimplemented.\n", tag());
uint8_t cr = submodule ? dmacr & 0x00ff : dmacr >> 8;
state[submodule].mode_16 = cr & 0x80;
state[submodule].autoreq = false;
state[submodule].suspended = true;
int32_t step = state[submodule].mode_16 ? 2 : 1;
if(!(cr & 0x20)) {
// Sequential mode
state[submodule].count = etcr[submodule] ? etcr[submodule] : 0x10000;
state[submodule].incs = cr & 0x40 ? -step : step;
} else if(dtie & (1 << submodule)) {
// Idle mode
state[submodule].count = etcr[submodule] ? etcr[submodule] : 0x10000;
state[submodule].incs = 0;
} else {
// Repeat mode
state[submodule].count = etcr[submodule] & 0x00ff ? etcr[submodule] & 0x00ff : 0x100;
state[submodule].incs = cr & 0x40 ? -step : step;
}
if(cr & 0x10) {
state[submodule].source = 0xff0000 | ioar[submodule];
state[submodule].dest = mar[submodule];
state[submodule].incd = state[submodule].incs;
state[submodule].incs = 0;
} else {
state[submodule].source = mar[submodule];
state[submodule].dest = 0xff0000 | ioar[submodule];
state[submodule].incd = 0;
}
cpu->set_current_dma(state + submodule);
}
}
@ -431,6 +541,20 @@ void h8_dma_channel_device::count_done(int submodule)
throw emu_fatalerror("%s: DMA end-of-transfer interrupt in full address/normal mode unimplemented.\n", tag());
}
} else {
throw emu_fatalerror("%s: DMA count done in short address mode unimplemented.\n", tag());
uint8_t cr = submodule ? dmacr & 0x00ff : dmacr >> 8;
if((cr & 0x20) && !(dtie & (1 << submodule))) {
// Repeat mode
state[submodule].count = etcr[submodule] & 0x00ff ? etcr[submodule] & 0x00ff : 0x100;
if(cr & 0x10)
state[submodule].dest = mar[submodule];
else
state[submodule].source = mar[submodule];
} else {
dte &= ~(1 << submodule);
dmac->clear_dte(state[0].id + submodule);
dtcr[submodule] &= ~0x80; // clear DTE (for H8H)
if(dtie & (1 << submodule))
throw emu_fatalerror("%s: DMA end-of-transfer interrupt in short address mode unimplemented.\n", tag());
}
}
}

View File

@ -109,7 +109,9 @@ public:
uint16_t maral_r();
void maral_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t ioara_r();
uint8_t ioara8_r();
void ioara_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void ioara8_w(uint8_t data);
uint16_t etcra_r();
void etcra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t marbh_r();
@ -117,7 +119,9 @@ public:
uint16_t marbl_r();
void marbl_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t ioarb_r();
uint8_t ioarb8_r();
void ioarb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void ioarb8_w(uint8_t data);
uint16_t etcrb_r();
void etcrb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t dmacr_r();