]> localhost Git - WindEmu.git/commitdiff
lots of arm710a fixes
authorAsh Wolf <ninji@wuffs.org>
Sun, 22 Dec 2019 13:45:46 +0000 (13:45 +0000)
committerAsh Wolf <ninji@wuffs.org>
Sun, 22 Dec 2019 13:45:46 +0000 (13:45 +0000)
WindCore/arm710a.cpp
WindCore/arm710a.h
WindCore/emu.cpp
WindQt/mainwindow.cpp
WindQt/mainwindow.ui

index 41434f37bcd47cd05a5485757f4b15e88b33af4f..1dff3831e295eb9f3e9cbb31b55bf7a71f40cbd5 100644 (file)
@@ -104,6 +104,7 @@ uint32_t ARM710a::tick() {
                if (insnFault != NoFault) {
                        // Raise a prefetch error
                        // These do not set FSR or FAR
+                       log("prefetch error!");
                        raiseException(Abort32, GPRs[15] - 8, 0xC);
                } else {
                        clocks += executeInstruction(insn);
@@ -131,6 +132,7 @@ static inline bool extract1(uint32_t value, uint32_t bit) {
 
 uint32_t ARM710a::executeInstruction(uint32_t i) {
        uint32_t cycles = 1;
+//     log("executing insn %08x @ %08x", i, GPRs[15] - 0xC);
 
        // a big old dispatch thing here
        // but first, conditions!
@@ -191,59 +193,64 @@ uint32_t ARM710a::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R
                                op2 -= 4;
                }
 
-               switch (extract(Operand2, 6, 5)) {
-               case 0: // Logical Left (LSL)
-                       if (shiftBy == 0) {
-                               shifterCarryOutput = flagC();
-                               // no change to op2!
-                       } else if (shiftBy <= 31) {
-                               shifterCarryOutput = extract1(op2, 31 - shiftBy);
-                               op2 <<= shiftBy;
-                       } else if (shiftBy == 32) {
-                               shifterCarryOutput = extract1(op2, 0);
-                               op2 = 0;
-                       } else /*if (shiftBy >= 33)*/ {
-                               shifterCarryOutput = false;
-                               op2 = 0;
-                       }
-                       break;
-               case 1: // Logical Right (LSR)
-                       if (shiftBy == 0 || shiftBy == 32) {
-                               shifterCarryOutput = extract1(op2, 31);
-                               op2 = 0;
-                       } else if (shiftBy <= 31) {
-                               shifterCarryOutput = extract1(op2, shiftBy - 1);
-                               op2 >>= shiftBy;
-                       } else /*if (shiftBy >= 33)*/ {
-                               shifterCarryOutput = false;
-                               op2 = 0;
-                       }
-                       break;
-               case 2: // Arithmetic Right (ASR)
-                       if (shiftBy == 0 || shiftBy >= 32) {
-                               shifterCarryOutput = extract1(op2, 31);
-                               op2 = (int32_t)op2 >> 31;
-                       } else /*if (shiftBy <= 31)*/ {
-                               shifterCarryOutput = extract1(op2, shiftBy - 1);
-                               op2 = (int32_t)op2 >> shiftBy;
-                       }
-                       break;
-               case 3: // Rotate Right (ROR)
-                       if (shiftBy == 0) { // treated as RRX
-                               shifterCarryOutput = op2 & 1;
-                               op2 >>= 1;
-                               op2 |= flagC() ? 0x80000000 : 0;
-                       } else {
-                               shiftBy %= 32;
-                               if (shiftBy == 0) { // like 32
+               if (extract(Operand2, 4, 4) && (shiftBy == 0)) {
+                       // register shift by 0 never does anything
+                       shifterCarryOutput = flagC();
+               } else {
+                       switch (extract(Operand2, 6, 5)) {
+                       case 0: // Logical Left (LSL)
+                               if (shiftBy == 0) {
+                                       shifterCarryOutput = flagC();
+                                       // no change to op2!
+                               } else if (shiftBy <= 31) {
+                                       shifterCarryOutput = extract1(op2, 31 - shiftBy);
+                                       op2 <<= shiftBy;
+                               } else if (shiftBy == 32) {
+                                       shifterCarryOutput = extract1(op2, 0);
+                                       op2 = 0;
+                               } else /*if (shiftBy >= 33)*/ {
+                                       shifterCarryOutput = false;
+                                       op2 = 0;
+                               }
+                               break;
+                       case 1: // Logical Right (LSR)
+                               if (shiftBy == 0 || shiftBy == 32) {
                                        shifterCarryOutput = extract1(op2, 31);
-                                       // no change to op2
-                               } else {
+                                       op2 = 0;
+                               } else if (shiftBy <= 31) {
                                        shifterCarryOutput = extract1(op2, shiftBy - 1);
-                                       op2 = ROR(op2, shiftBy);
+                                       op2 >>= shiftBy;
+                               } else /*if (shiftBy >= 33)*/ {
+                                       shifterCarryOutput = false;
+                                       op2 = 0;
+                               }
+                               break;
+                       case 2: // Arithmetic Right (ASR)
+                               if (shiftBy == 0 || shiftBy >= 32) {
+                                       shifterCarryOutput = extract1(op2, 31);
+                                       op2 = (int32_t)op2 >> 31;
+                               } else /*if (shiftBy <= 31)*/ {
+                                       shifterCarryOutput = extract1(op2, shiftBy - 1);
+                                       op2 = (int32_t)op2 >> shiftBy;
+                               }
+                               break;
+                       case 3: // Rotate Right (ROR)
+                               if (shiftBy == 0) { // treated as RRX
+                                       shifterCarryOutput = op2 & 1;
+                                       op2 >>= 1;
+                                       op2 |= flagC() ? 0x80000000 : 0;
+                               } else {
+                                       shiftBy %= 32;
+                                       if (shiftBy == 0) { // like 32
+                                               shifterCarryOutput = extract1(op2, 31);
+                                               // no change to op2
+                                       } else {
+                                               shifterCarryOutput = extract1(op2, shiftBy - 1);
+                                               op2 = ROR(op2, shiftBy);
+                                       }
                                }
+                               break;
                        }
-                       break;
                }
        } else {
                // IMMEDIATE
@@ -252,7 +259,6 @@ uint32_t ARM710a::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R
 
                uint32_t Rotate = extract(Operand2, 11, 8);
                uint32_t Imm = extract(Operand2, 7, 0);
-               Imm = (uint32_t)(int8_t)Imm;
                op2 = ROR(Imm, Rotate * 2);
                shifterCarryOutput = flagC(); // correct? unsure...
        }
@@ -269,7 +275,7 @@ uint32_t ARM710a::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R
        flags |= (CPSR & CPSR_V);
 
 #define ADD_OP(a, b, c) \
-       result = a + b + (uint32_t)(c); \
+       result = (uint64_t)(a) + (uint64_t)(b) + (uint64_t)(c); \
        flags |= (result & 0xFFFFFFFF) ? 0 : CPSR_Z; \
        flags |= (result & 0x80000000) ? CPSR_N : 0; \
        flags |= (result & 0x100000000) ? CPSR_C : 0; \
@@ -301,9 +307,11 @@ uint32_t ARM710a::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R
                // Output-less opcodes: special behaviour
                if (S) {
                        CPSR = (CPSR & ~CPSR_FlagMask) | flags;
+//                     log("CPSR setflags=%08x results in CPSR=%08x", flags, CPSR);
                } else if (Opcode == 8) {
                        // MRS, CPSR -> Reg
                        GPRs[Rd] = CPSR;
+                       log("r%d <- CPSR(%08x)", Rd, GPRs[Rd]);
                } else if (Opcode == 9) {
                        // MSR, Reg -> CPSR
                        bool canChangeMode = extract1(Rn, 0);
@@ -311,27 +319,33 @@ uint32_t ARM710a::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R
                                auto newCPSR = GPRs[extract(Operand2, 3, 0)];
                                switchMode(modeFromCPSR(newCPSR));
                                CPSR = newCPSR;
+                               log("CPSR change privileged: %08x", CPSR);
                        } else {
                                // for the flag-only version, immediates are allowed
                                // so we just re-use what was calculated earlier...
                                auto newFlag = I ? op2 : GPRs[extract(Operand2, 3, 0)];
                                CPSR &= ~CPSR_FlagMask;
                                CPSR |= (newFlag & CPSR_FlagMask);
+                               log("CPSR change unprivileged: new=%08x result=%08x", newFlag, CPSR);
                        }
                } else if (Opcode == 0xA) {
                        // MRS, SPSR -> Reg
-                       if (isPrivileged())
+                       if (isPrivileged()) {
                                GPRs[Rd] = SPSRs[currentBank()];
+                               log("r%d <- SPSR(%08x)", Rd, GPRs[Rd]);
+                       }
                } else /*if (Opcode == 0xB)*/ {
                        bool canChangeMode = extract1(Rn, 0);
                        if (isPrivileged()) {
                                if (canChangeMode) {
                                        SPSRs[currentBank()] = GPRs[extract(Operand2, 3, 0)];
+                                       log("SPSR change privileged: %08x", SPSRs[currentBank()]);
                                } else {
                                        // same hat
                                        auto newFlag = I ? op2 : GPRs[extract(Operand2, 3, 0)];
                                        SPSRs[currentBank()] &= ~CPSR_FlagMask;
                                        SPSRs[currentBank()] |= (newFlag & CPSR_FlagMask);
+                                       log("SPSR change unprivileged: new=%08x result=%08x", newFlag, SPSRs[currentBank()]);
                                }
                        }
                }
@@ -348,9 +362,11 @@ uint32_t ARM710a::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R
                                auto saved = SPSRs[currentBank()];
                                switchMode(modeFromCPSR(saved));
                                CPSR = saved;
+                               log("dataproc restore CPSR: %08x", CPSR);
                        }
                } else if (S) {
                        CPSR = (CPSR & ~CPSR_FlagMask) | flags;
+//                     log("dataproc flag change: flags=%08x CPSR=%08x", flags, CPSR);
                }
        }
 
@@ -400,7 +416,7 @@ uint32_t ARM710a::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t
        auto valueSize = extract1(IPUBWL, 2) ? V8 : V32;
        bool up = extract1(IPUBWL, 3);
        bool preIndex = extract1(IPUBWL, 4);
-       bool immediate = extract1(IPUBWL, 5);
+       bool immediate = !extract1(IPUBWL, 5);
 
        // calculate the offset
        uint32_t calcOffset;
@@ -438,10 +454,8 @@ uint32_t ARM710a::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t
                }
        } else {
                // IMMEDIATE
-               uint32_t Rotate = extract(offset, 11, 8);
-               uint32_t Imm = extract(offset, 7, 0);
-               Imm = (uint32_t)(int8_t)Imm;
-               calcOffset = ROR(Imm, Rotate * 2);
+               // No rotation or anything here
+               calcOffset = offset;
        }
 
        uint32_t base = GPRs[Rn];
@@ -458,8 +472,10 @@ uint32_t ARM710a::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t
                if (changeModes) switchMode(User32);
                auto readResult = readVirtual(transferAddr, valueSize);
                if (changeModes) switchMode(saveMode);
-               if (readResult.first.has_value())
+               if (readResult.first.has_value()) {
                        GPRs[Rd] = readResult.first.value();
+                       if (Rd == 15) prefetchCount = 0;
+               }
                fault = readResult.second;
        } else {
                uint32_t value = GPRs[Rd];
@@ -538,6 +554,9 @@ uint32_t ARM710a::execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t re
                }
        }
 
+       if (registerList & 0x8000)
+               prefetchCount = 0;
+
        // datasheet specifies that base register must be
        // restored if an error occurs during LDM
        if (load && fault != NoFault)
@@ -741,7 +760,7 @@ pair<MaybeU32, ARM710a::MMUFault> ARM710a::readVirtual(uint32_t virtAddr, ValueS
                if (auto v = readPhysical(virtAddr, valueSize); v.has_value())
                        return make_pair(v.value(), NoFault);
                else
-                       return make_pair(MaybeU32(), NonMMUError);
+                       return make_pair(MaybeU32(), encodeFault(NonMMUError, 0, virtAddr));
        }
 
        auto translated = translateAddressUsingTlb(virtAddr);
@@ -775,7 +794,7 @@ ARM710a::MMUFault ARM710a::writeVirtual(uint32_t value, uint32_t virtAddr, Value
        if (!isMMUEnabled()) {
                // direct virtual -> physical mapping, sans MMU
                if (!writePhysical(value, virtAddr, valueSize))
-                       return NonMMUError;
+                       return encodeFault(NonMMUError, 0, virtAddr);
        } else {
                auto translated = translateAddressUsingTlb(virtAddr);
                if (holds_alternative<MMUFault>(translated))
@@ -965,12 +984,61 @@ ARM710a::MMUFault ARM710a::checkAccessPermissions(ARM710a::TlbEntry *entry, uint
 void ARM710a::reportFault(MMUFault fault) {
        if (fault != NoFault) {
                if ((fault & 0xF) != NonMMUError) {
-                       cp15_faultStatus = fault & 0xFFFF;
-                       cp15_faultAddress = fault >> 32;
+                       cp15_faultStatus = fault & (MMUFaultTypeMask | MMUFaultDomainMask);
+                       cp15_faultAddress = fault >> MMUFaultAddressShift;
                }
 
+               static const char *faultTypes[] = {
+                       "NoFault",
+                       "AlignmentFault",
+                       "???",
+                       "NonMMUError",
+                       "SectionLinefetchError",
+                       "SectionTranslationFault",
+                       "PageLinefetchError",
+                       "PageTranslationFault",
+                       "SectionOtherBusError",
+                       "SectionDomainFault",
+                       "PageOtherBusError",
+                       "PageDomainFault",
+                       "Lv1TranslationError",
+                       "SectionPermissionFault",
+                       "Lv2TranslationError",
+                       "PagePermissionFault"
+               };
+               log("⚠️ Fault type=%s domain=%d address=%08x pc=%08x lr=%08x",
+                       faultTypes[fault & MMUFaultTypeMask],
+                       (fault & MMUFaultDomainMask) >> MMUFaultDomainShift,
+                       fault >> MMUFaultAddressShift,
+                       GPRs[15], GPRs[14]);
+
                // this signals a branch to DataAbort after the
                // instruction is done executing
                faultTriggeredThisCycle = true;
        }
 }
+
+
+void ARM710a::log(const char *format, ...) {
+       if (logger) {
+               char buffer[1024];
+
+               va_list vaList;
+               va_start(vaList, format);
+               vsnprintf(buffer, sizeof(buffer), format, vaList);
+               va_end(vaList);
+
+               logger(buffer);
+       }
+}
+
+
+void ARM710a::test() {
+       uint64_t result;
+       uint32_t flags = 0;
+       uint32_t v = 0x10000000;
+
+       SUB_OP(v, v, 1);
+
+       log("RESULT:%llx FLAGS:%08x", result, flags);
+}
index f4116d6bea9547f0d799d8031c024a28c5623df9..30fc2a5f7ab03d6c53a9886b680a61ba8147b6e6 100644 (file)
@@ -18,6 +18,8 @@ typedef optional<uint32_t> MaybeU32;
 class ARM710a
 {
 public:
+       void test();
+
        enum ValueSize { V8 = 0, V32 = 1 };
 
        enum MMUFault : uint64_t {
@@ -42,8 +44,11 @@ public:
                // so we are reusing it for nefarious purposes
                NonMMUError             = 3,
 
+               MMUFaultTypeMask        = 0xF,
                MMUFaultDomainMask      = 0xF0,
-               MMUFaultAddressMask     = 0xFFFFFFFF00000000
+               MMUFaultDomainShift     = 4,
+               MMUFaultAddressMask     = 0xFFFFFFFF00000000,
+               MMUFaultAddressShift    = 32
        };
 
 
@@ -83,6 +88,7 @@ public:
        void requestIRQ(); // pull nIRQ low
        void reset();      // pull nRESET low
 
+       bool instructionReady() const { return (prefetchCount == 2); }
        uint32_t tick();   // run the chip for at least 1 clock cycle
 
        MaybeU32 readVirtualDebug(uint32_t virtAddr, ValueSize valueSize);
@@ -94,8 +100,14 @@ public:
        virtual bool writePhysical(uint32_t value, uint32_t physAddr, ARM710a::ValueSize valueSize) = 0;
 
        uint32_t getGPR(int index) const { return GPRs[index]; }
+       uint32_t getCPSR() const { return CPSR; }
 
+       void setLogger(std::function<void(const char *)> newLogger) { logger = newLogger; }
+protected:
+       void log(const char *format, ...);
 private:
+       std::function<void(const char *)> logger;
+
        enum { Nop = 0xE1A00000 };
 
        enum Mode : uint8_t {
@@ -158,22 +170,22 @@ private:
        bool flagN() const { return CPSR & CPSR_N; }
        bool checkCondition(int cond) const {
                switch (cond) {
-               case 0:   return flagZ();
-               case 1:   return !flagZ();
-               case 2:   return flagC();
-               case 3:   return !flagC();
-               case 4:   return flagN();
-               case 5:   return !flagN();
-               case 6:   return flagV();
-               case 7:   return !flagV();
-               case 8:   return flagC() && !flagZ();
-               case 9:   return !flagC() || flagZ();
-               case 0xA: return flagN() == flagV();
-               case 0xB: return flagN() != flagV();
-               case 0xC: return !flagZ() && (flagN() == flagV());
-               case 0xD: return flagZ() || (flagN() != flagV());
-               case 0xE: return true;
-               /*case 0xF:*/
+               /*EQ*/ case 0:   return flagZ();
+               /*NE*/ case 1:   return !flagZ();
+               /*CS*/ case 2:   return flagC();
+               /*CC*/ case 3:   return !flagC();
+               /*MI*/ case 4:   return flagN();
+               /*PL*/ case 5:   return !flagN();
+               /*VS*/ case 6:   return flagV();
+               /*VC*/ case 7:   return !flagV();
+               /*HI*/ case 8:   return flagC() && !flagZ();
+               /*LS*/ case 9:   return !flagC() || flagZ();
+               /*GE*/ case 0xA: return flagN() == flagV();
+               /*LT*/ case 0xB: return flagN() != flagV();
+               /*GT*/ case 0xC: return !flagZ() && (flagN() == flagV());
+               /*LE*/ case 0xD: return flagZ() || (flagN() != flagV());
+               /*AL*/ case 0xE: return true;
+               /*NV*/ /*case 0xF:*/
                default:  return false;
                }
        }
index 4234af9b8d2f8b5e6e851a0b8c4994ddeceb2707..d878c9ebee6eaa7a59b383f792b555cef50af7b0 100644 (file)
@@ -224,6 +224,8 @@ MaybeU32 Emu::readPhysical(uint32_t physAddr, ValueSize valueSize) {
                else if (region == 0xD1)
                        return MemoryBlockD1[physAddr & MemoryBlockMask];
 #endif
+               else if (region >= 0xC0)
+                       return 0xFF; // just throw accesses to unmapped RAM away
        } else {
                uint32_t result;
                if (region == 0)
@@ -244,6 +246,8 @@ MaybeU32 Emu::readPhysical(uint32_t physAddr, ValueSize valueSize) {
                else if (region == 0xD1)
                        LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockD1);
 #endif
+               else if (region >= 0xC0)
+                       return 0xFFFFFFFF; // just throw accesses to unmapped RAM away
                else
                        return {};
                return result;
@@ -267,6 +271,8 @@ bool Emu::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize)
                else if (region == 0xD1)
                        MemoryBlockD1[physAddr & MemoryBlockMask] = (uint8_t)value;
 #endif
+               else if (region >= 0xC0)
+                       return true; // just throw accesses to unmapped RAM away
                else if (region == 0x20 && physAddr <= 0x20000FFF)
                        etna.writeReg8(physAddr & 0xFFF, value);
                else if (region == 0x80 && physAddr <= 0x80000FFF)
@@ -287,6 +293,8 @@ bool Emu::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize)
                else if (region == 0xD1)
                        STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockD1);
 #endif
+               else if (region >= 0xC0)
+                       return true; // just throw accesses to unmapped RAM away
                else if (region == 0x20 && physAddr <= 0x20000FFF)
                        etna.writeReg32(physAddr & 0xFFF, value);
                else if (region == 0x80 && physAddr <= 0x80000FFF)
@@ -311,6 +319,7 @@ void Emu::configure() {
        nextTickAt = TICK_INTERVAL;
        rtc = getRTC();
 
+       setProcessorID(0x41807100);
        reset();
 }
 
@@ -352,11 +361,15 @@ void Emu::executeUntil(int64_t cycles) {
                        // keep the clock moving
                        passedCycles++;
                } else {
+                       if (auto v = virtToPhys(getGPR(15) - 0xC); v.has_value() && instructionReady())
+                               debugPC(v.value());
                        passedCycles += tick();
 
                        uint32_t new_pc = getGPR(15) - 0xC;
-                       if (_breakpoints.find(new_pc) != _breakpoints.end())
+                       if (_breakpoints.find(new_pc) != _breakpoints.end()) {
+                               log("⚠️ Breakpoint triggered at %08x!\n", new_pc);
                                return;
+                       }
                }
        }
 }
@@ -426,14 +439,34 @@ void Emu::debugPC(uint32_t pc) {
                const char *wut = identifyObjectCon(container);
                if (wut) {
                        fetchName(obj, objName);
-                       printf("OBJS: added %s at %08x <%s>", wut, obj, objName);
                        if (strcmp(wut, "process") == 0) {
-                               fetchProcessFilename(obj, objName);
-                               printf(" <%s>", objName);
+                               char procName[1000];
+                               fetchProcessFilename(obj, procName);
+                               log("OBJS: added %s at %08x <%s> <%s>", wut, obj, objName, procName);
+                       } else {
+                               log("OBJS: added %s at %08x <%s>", wut, obj, objName);
                        }
-                       printf("\n");
                }
        }
+
+       if (pc == 0x6D8) {
+               uint32_t virtAddr = getGPR(0);
+               uint32_t physAddr = getGPR(1);
+               uint32_t btIndex = getGPR(2);
+               uint32_t regionSize = getGPR(3);
+               log("KERNEL MMU SECTION: v:%08x p:%08x size:%08x idx:%02x",
+                       virtAddr, physAddr, regionSize, btIndex);
+       }
+       if (pc == 0x710) {
+               uint32_t virtAddr = getGPR(0);
+               uint32_t physAddr = getGPR(1);
+               uint32_t btIndex = getGPR(2);
+               uint32_t regionSize = getGPR(3);
+               uint32_t pageTableA = getGPR(4);
+               uint32_t pageTableB = getGPR(5);
+               log("KERNEL MMU PAGES: v:%08x p:%08x size:%08x idx:%02x tableA:%08x tableB:%08x",
+                       virtAddr, physAddr, regionSize, btIndex, pageTableA, pageTableB);
+       }
 }
 
 
index 36a385e9e31c49b007ff45a24512c26b58752e24..31ad8006c13c2b5fbd2a883f75140aebbbfe2089 100644 (file)
@@ -10,9 +10,14 @@ MainWindow::MainWindow(QWidget *parent) :
     ui(new Ui::MainWindow)
 {
     ui->setupUi(this);
+       ui->logView->setMaximumBlockCount(1000);
 
     emu = new Emu;
        emu->loadROM("/Users/ash/src/psion/Sys$rom.bin");
+       emu->setLogger([&](const char *str) {
+               ui->logView->appendPlainText(str);
+       });
+       emu->test();
 
     timer = new QTimer(this);
     timer->setInterval(1000/64);
@@ -32,8 +37,25 @@ void MainWindow::updateScreen()
 
        updateMemory();
 
+       char flagDisplay[] = {
+               (emu->getCPSR() & 0x80000000) ? 'N' : '-',
+               (emu->getCPSR() & 0x40000000) ? 'Z' : '-',
+               (emu->getCPSR() & 0x20000000) ? 'C' : '-',
+               (emu->getCPSR() & 0x10000000) ? 'V' : '-',
+               0
+       };
+       const char *modeName = "???";
+       switch (emu->getCPSR() & 0x1F) {
+       case 0x10: modeName = "User"; break;
+       case 0x11: modeName = "FIQ"; break;
+       case 0x12: modeName = "IRQ"; break;
+       case 0x13: modeName = "Supervisor"; break;
+       case 0x17: modeName = "Abort"; break;
+       case 0x1B: modeName = "Undefined"; break;
+       }
+
     ui->regsLabel->setText(
-                               QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / R7: %8\nR8: %9 / R9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: %14 / LR: %15 / PC: %16")
+                               QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / R7: %8\nR8: %9 / R9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: %14 / LR: %15 / PC: %16\n%17 / Mode: %18")
                 .arg(emu->getGPR(0), 8, 16)
                 .arg(emu->getGPR(1), 8, 16)
                 .arg(emu->getGPR(2), 8, 16)
@@ -50,11 +72,13 @@ void MainWindow::updateScreen()
                 .arg(emu->getGPR(13), 8, 16)
                 .arg(emu->getGPR(14), 8, 16)
                 .arg(emu->getGPR(15), 8, 16)
+                               .arg(flagDisplay)
+                               .arg(modeName)
                 );
 
     // show a crude disassembly
     const int context = 8 * 4;
-    uint32_t pc = emu->getGPR(15) - 4;
+       uint32_t pc = emu->getGPR(15) - 8;
     uint32_t minCode = pc - context;
        if (minCode >= (UINT32_MAX - context))
         minCode = 0;
@@ -64,7 +88,7 @@ void MainWindow::updateScreen()
 
        QStringList codeLines;
        for (uint32_t addr = minCode; addr >= minCode && addr <= maxCode; addr += 4) {
-               const char *prefix = (addr == pc) ? "==>" : "   ";
+               const char *prefix = (addr == pc) ? (emu->instructionReady() ? "==>" : "...") : "   ";
         struct ARMInstructionInfo info;
         char buffer[512];
 
@@ -228,8 +252,9 @@ void MainWindow::on_stopButton_clicked()
 
 void MainWindow::on_stepTickButton_clicked()
 {
-    emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED * 2));
-    updateScreen();
+//    emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED * 2));
+       emu->executeUntil(emu->currentCycles() + 25000);
+       updateScreen();
 }
 
 void MainWindow::on_stepInsnButton_clicked()
index 7ddbdd57ad69a3fe39855e654e1e9b85e9344b23..c2250b661d91b4ce972cdd0e99f549dd805b4554 100644 (file)
       </property>
      </widget>
     </item>
-    <item row="3" column="0" colspan="5">
-     <widget class="QLabel" name="regsLabel">
-      <property name="font">
-       <font>
-        <family>Courier New</family>
-       </font>
-      </property>
-      <property name="text">
-       <string/>
-      </property>
-     </widget>
-    </item>
-    <item row="1" column="3">
-     <widget class="QPushButton" name="startButton">
-      <property name="text">
-       <string>Start</string>
-      </property>
-     </widget>
-    </item>
-    <item row="2" column="4">
-     <widget class="QPushButton" name="stepTickButton">
-      <property name="text">
-       <string>Step (Tick)</string>
-      </property>
-     </widget>
-    </item>
-    <item row="0" column="0" colspan="6">
-     <widget class="QLabel" name="screen">
-      <property name="focusPolicy">
-       <enum>Qt::ClickFocus</enum>
-      </property>
-      <property name="text">
-       <string/>
-      </property>
-     </widget>
-    </item>
-    <item row="2" column="3">
-     <widget class="QPushButton" name="stepInsnButton">
-      <property name="text">
-       <string>Step (Insn)</string>
-      </property>
-     </widget>
-    </item>
-    <item row="1" column="2">
-     <spacer name="horizontalSpacer">
-      <property name="orientation">
-       <enum>Qt::Horizontal</enum>
-      </property>
-      <property name="sizeHint" stdset="0">
-       <size>
-        <width>40</width>
-        <height>20</height>
-       </size>
-      </property>
-     </spacer>
-    </item>
-    <item row="1" column="4">
-     <widget class="QPushButton" name="stopButton">
-      <property name="enabled">
-       <bool>false</bool>
-      </property>
-      <property name="text">
-       <string>Stop</string>
-      </property>
-     </widget>
-    </item>
     <item row="4" column="0" colspan="5">
      <widget class="QTabWidget" name="tabWidget">
       <property name="currentIndex">
       </widget>
      </widget>
     </item>
+    <item row="3" column="0" colspan="5">
+     <widget class="QLabel" name="regsLabel">
+      <property name="font">
+       <font>
+        <family>Courier New</family>
+       </font>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="3">
+     <widget class="QPushButton" name="startButton">
+      <property name="text">
+       <string>Start</string>
+      </property>
+     </widget>
+    </item>
+    <item row="2" column="4">
+     <widget class="QPushButton" name="stepTickButton">
+      <property name="text">
+       <string>Step (Tick)</string>
+      </property>
+     </widget>
+    </item>
+    <item row="0" column="0" colspan="6">
+     <widget class="QLabel" name="screen">
+      <property name="focusPolicy">
+       <enum>Qt::ClickFocus</enum>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+     </widget>
+    </item>
+    <item row="2" column="3">
+     <widget class="QPushButton" name="stepInsnButton">
+      <property name="text">
+       <string>Step (Insn)</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="2">
+     <spacer name="horizontalSpacer">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>40</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item row="1" column="4">
+     <widget class="QPushButton" name="stopButton">
+      <property name="enabled">
+       <bool>false</bool>
+      </property>
+      <property name="text">
+       <string>Stop</string>
+      </property>
+     </widget>
+    </item>
+    <item row="5" column="0" colspan="5">
+     <widget class="QPlainTextEdit" name="logView"/>
+    </item>
    </layout>
   </widget>
  </widget>