fix broken timekeeping on 5mx and touch panel on 5mx

This commit is contained in:
Ash Wolf 2019-12-25 19:25:34 +00:00
parent 83c1dcadf7
commit 0aa59317ba
5 changed files with 53 additions and 15 deletions

View File

@ -9,7 +9,7 @@ Psion 5mx (EPOC R5) features:
- ✅ LCD: partially implemented - ✅ LCD: partially implemented
- ✅ Keyboard: implemented - ✅ Keyboard: implemented
- ❌ Touch panel: not implemented - ✅ Touch panel: implemented
- ❌ Audio: not implemented - ❌ Audio: not implemented
- ❌ Serial/UART support: stubbed out - ❌ Serial/UART support: stubbed out
- ❌ ETNA (PCMCIA/CompactFlash): mostly stubbed out - ❌ ETNA (PCMCIA/CompactFlash): mostly stubbed out
@ -20,7 +20,7 @@ Psion 5mx (EPOC R5) features:
Oregon Scientific Osaris (EPOC R4) features: Oregon Scientific Osaris (EPOC R4) features:
- ✅ LCD: implemented - ✅ LCD: implemented
- ✅ Keyboard: mostly implemented (key mappings wrong) - ✅ Keyboard: implemented (somewhat buggy)
- ✅ Touch panel: implemented - ✅ Touch panel: implemented
- ❌ Audio: not implemented - ❌ Audio: not implemented
- ❌ Serial/UART support: stubbed out - ❌ Serial/UART support: stubbed out

View File

@ -161,6 +161,8 @@ uint32_t ARM710::executeInstruction(uint32_t i) {
cycles += execSingleDataSwap(extract1(i,22), extract(i,19,16), extract(i,15,12), extract(i,3,0)); cycles += execSingleDataSwap(extract1(i,22), extract(i,19,16), extract(i,15,12), extract(i,3,0));
else if ((i & 0x0F8000F0) == 0x00000090) else if ((i & 0x0F8000F0) == 0x00000090)
cycles += execMultiply(extract(i,21,20), extract(i,19,16), extract(i,15,12), extract(i,11,8), extract(i,3,0)); cycles += execMultiply(extract(i,21,20), extract(i,19,16), extract(i,15,12), extract(i,11,8), extract(i,3,0));
else if ((i & 0x0F8000F0) == 0x00800090 && isTVersion)
cycles += execMultiplyLong(extract(i,22,20), extract(i,19,16), extract(i,15,12), extract(i,11,8), extract(i,3,0));
else if ((i & 0x0C000000) == 0x00000000) else if ((i & 0x0C000000) == 0x00000000)
cycles += execDataProcessing(extract1(i,25), extract(i,24,21), extract1(i,20), extract(i,19,16), extract(i,15,12), extract(i,11,0)); cycles += execDataProcessing(extract1(i,25), extract(i,24,21), extract1(i,20), extract(i,19,16), extract(i,15,12), extract(i,11,0));
else else
@ -399,6 +401,35 @@ uint32_t ARM710::execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs
return 0; return 0;
} }
// ARM710T only!
uint32_t ARM710::execMultiplyLong(uint32_t UAS, uint32_t RdHi, uint32_t RdLo, uint32_t Rs, uint32_t Rm)
{
// no need for R15 fuckery
// datasheet says it's not allowed here
uint64_t result;
if (UAS & 4) // unsigned
result = (uint64_t)GPRs[Rm] * (uint64_t)GPRs[Rs];
else // signed
result = (uint64_t)((int64_t)GPRs[Rm] * (int64_t)GPRs[Rs]);
if (UAS & 2) {
// accumulate
uint64_t addend = (uint64_t)GPRs[RdLo] | ((uint64_t)GPRs[RdHi] << 32);
result += addend;
}
if (UAS & 1) {
CPSR &= ~(CPSR_N | CPSR_Z);
CPSR |= result ? 0 : CPSR_Z;
CPSR |= (result & 0x8000000000000000) ? CPSR_N : 0;
}
GPRs[RdLo] = result & 0xFFFFFFFF;
GPRs[RdHi] = result >> 32;
return 0;
}
uint32_t ARM710::execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm) uint32_t ARM710::execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm)
{ {
auto valueSize = B ? V8 : V32; auto valueSize = B ? V8 : V32;

View File

@ -287,6 +287,7 @@ private:
uint32_t execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t Rn, uint32_t Rd, uint32_t Operand2); uint32_t execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t Rn, uint32_t Rd, uint32_t Operand2);
uint32_t execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs, uint32_t Rm); uint32_t execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs, uint32_t Rm);
uint32_t execMultiplyLong(uint32_t UAS, uint32_t RdHi, uint32_t RdLo, uint32_t Rs, uint32_t Rm);
uint32_t execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm); uint32_t execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm);
uint32_t execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t Rd, uint32_t offset); uint32_t execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t Rd, uint32_t offset);
uint32_t execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t registerList); uint32_t execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t registerList);

View File

@ -79,14 +79,14 @@ Etna::Etna(ARM710 *owner) {
chk ^= prom[i]; chk ^= prom[i];
// EPOC is expecting 66 // EPOC is expecting 66
prom[0x7F] = chk ^ 66; prom[0x7F] = chk ^ 66;
} }
uint32_t Etna::readReg8(uint32_t reg) uint32_t Etna::readReg8(uint32_t reg)
{ {
if (!promReadActive) // if (!promReadActive)
printf("ETNA readReg8: reg=%s @ pc=%08x,lr=%08x\n", nameReg(reg), owner->getGPR(15) - 4, owner->getGPR(14)); // owner->log("ETNA readReg8: reg=%s @ pc=%08x,lr=%08x", nameReg(reg), owner->getGPR(15) - 4, owner->getGPR(14));
switch (reg) { switch (reg) {
case regIntClear: return 0; case regIntClear: return 0;
case regSktVarA0: return 1; // will store some status flags case regSktVarA0: return 1; // will store some status flags
@ -100,14 +100,14 @@ uint32_t Etna::readReg8(uint32_t reg)
uint32_t Etna::readReg32(uint32_t reg) uint32_t Etna::readReg32(uint32_t reg)
{ {
// may be able to remove this, p. sure Etna is byte addressing only // may be able to remove this, p. sure Etna is byte addressing only
printf("ETNA readReg32: reg=%x\n", reg); owner->log("ETNA readReg32: reg=%x", reg);
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
void Etna::writeReg8(uint32_t reg, uint8_t value) void Etna::writeReg8(uint32_t reg, uint8_t value)
{ {
if (!promReadActive) if (!promReadActive)
printf("ETNA writeReg8: reg=%s value=%02x @ pc=%08x,lr=%08x\n", nameReg(reg), value, owner->getGPR(15) - 4, owner->getGPR(14)); owner->log("ETNA writeReg8: reg=%s value=%02x @ pc=%08x,lr=%08x", nameReg(reg), value, owner->getGPR(15) - 4, owner->getGPR(14));
switch (reg) { switch (reg) {
case regIntClear: pendingInterrupts &= ~value; break; case regIntClear: pendingInterrupts &= ~value; break;
case regWake1: wake1 = value; break; case regWake1: wake1 = value; break;
@ -118,7 +118,7 @@ void Etna::writeReg8(uint32_t reg, uint8_t value)
void Etna::writeReg32(uint32_t reg, uint32_t value) void Etna::writeReg32(uint32_t reg, uint32_t value)
{ {
// may be able to remove this, p. sure Etna is byte addressing only // may be able to remove this, p. sure Etna is byte addressing only
printf("ETNA writeReg32: reg=%x value=%08x\n", reg, value); owner->log("ETNA writeReg32: reg=%x value=%08x", reg, value);
} }
void Etna::setPromBit0High() void Etna::setPromBit0High()

View File

@ -76,10 +76,8 @@ uint32_t Emulator::readReg32(uint32_t reg) {
// as per 5000A7B0 in 5mx rom // as per 5000A7B0 in 5mx rom
uint16_t ssiValue = 0; uint16_t ssiValue = 0;
switch (lastSSIRequest) { switch (lastSSIRequest) {
// case 0x9093: ssiValue = (uint16_t)(1156 - (touchY * 3.96)); break; case 0xD0D3: ssiValue = (uint16_t)(50 + (touchX * 5.7)); break;
// case 0xD0D3: ssiValue = (uint16_t)(2819 - (touchX * 3.91)); break; case 0x9093: ssiValue = (uint16_t)(3834 - (touchY * 13.225)); break;
case 0x9093: ssiValue = (uint16_t)(1156 - (touchY * 3.96)); break;
case 0xD0D3: ssiValue = (uint16_t)(1276 + (touchX * 3.91)); break;
case 0xA4A4: ssiValue = 3100; break; // MainBattery case 0xA4A4: ssiValue = 3100; break; // MainBattery
case 0xE4E4: ssiValue = 3100; break; // BackupBattery case 0xE4E4: ssiValue = 3100; break; // BackupBattery
} }
@ -97,11 +95,11 @@ uint32_t Emulator::readReg32(uint32_t reg) {
return 0; return 0;
} else if (reg == RTCDRL) { } else if (reg == RTCDRL) {
uint16_t v = rtc & 0xFFFF; uint16_t v = rtc & 0xFFFF;
// printf("RTCDRL: %04x\n", v); // log("RTCDRL: %04x", v);
return v; return v;
} else if (reg == RTCDRU) { } else if (reg == RTCDRU) {
uint16_t v = rtc >> 16; uint16_t v = rtc >> 16;
// printf("RTCDRU: %04x\n", v); // log("RTCDRU: %04x", v);
return v; return v;
} else if (reg == KSCAN) { } else if (reg == KSCAN) {
return kScan; return kScan;
@ -207,6 +205,14 @@ void Emulator::writeReg32(uint32_t reg, uint32_t value) {
tc2.load(value); tc2.load(value);
} else if (reg == TC2EOI) { } else if (reg == TC2EOI) {
pendingInterrupts &= ~(1 << TC2OI); pendingInterrupts &= ~(1 << TC2OI);
} else if (reg == RTCDRL) {
rtc &= 0xFFFF0000;
rtc |= (value & 0xFFFF);
log("RTC write lower: %04x", value);
} else if (reg == RTCDRU) {
rtc &= 0x0000FFFF;
rtc |= (value & 0xFFFF) << 16;
log("RTC write upper: %04x", value);
} else { } else {
// printf("RegWrite32 unknown:: pc=%08x reg=%03x value=%08x\n", getGPR(15)-4, reg, value); // printf("RegWrite32 unknown:: pc=%08x reg=%03x value=%08x\n", getGPR(15)-4, reg, value);
} }
@ -523,7 +529,7 @@ void Emulator::debugPC(uint32_t pc) {
case 15: n = "EButton3Up"; break; case 15: n = "EButton3Up"; break;
case 16: n = "ESwitchOff"; break; case 16: n = "ESwitchOff"; break;
} }
log("EVENT %s: tick=%d params=%08x,%08x", n, evtTick, evtParamA, evtParamB); log("EVENT %s: tick=%d params=%d,%d", n, evtTick, evtParamA, evtParamB);
} }
} }