Menu

#2025 Monitor assign registers

v3.x
open
nobody
None
GTK3
Monitor
2024-08-17
2024-05-01
robozz
No

The assign registers command (r) somehow repeats the current instruction when the command is used.

some examples:

(C:$e5cf) break 1000
BREAK: 1 C:$1000 (Stop on exec)
(C:$e5cf) break e147
BREAK: 2 C:$e147 (Stop on exec)

.C:1000  EE 20 D0    INC $D020
.C:1003  60          RTS

here, INC $D020 is executed twice when using the assign registers command:

#1 (Stop on  exec 1000)   16/$010,  17/$11
.C:1000  EE 20 D0    INC $D020      - A:00 X:00 Y:00 SP:f7 ..-.....   13150889
(C:$1000) r a = ff
(C:$1000) x
#1 (Stop on  exec 1000)   16/$010,  23/$17
.C:1000  EE 20 D0    INC $D020      - A:FF X:00 Y:00 SP:f7 ..-.....   13150895
(C:$1000) x
#2 (Stop on  exec e147)   16/$010,  35/$23
.C:e147  08          PHP            - A:FF X:00 Y:00 SP:f9 ..-...Z.   13150907
(C:$e147) chis 4
.C:e144  6C 14 00    JMP ($0014)    A:00 X:00 Y:00 SP:f7 ..-.....     13150884
.C:1000  EE 20 D0    INC $D020      A:ff X:00 Y:00 SP:f7 ..-.....     13150889
.C:1000  EE 20 D0    INC $D020      A:ff X:00 Y:00 SP:f7 ..-.....     13150895
.C:1003  60          RTS            A:ff X:00 Y:00 SP:f7 ..-...Z.     13150901
(C:$e147)
.C:1000  E8          INX
.C:1001  8E 20 D0    STX $D020
.C:1004  60          RTS

here, INX is executed twice, but x remains unchanged the first time:

#1 (Stop on  exec 1000)  268/$10c,  16/$10
.C:1000  E8          INX            - A:00 X:00 Y:00 SP:f7 ..-.....   11672908
(C:$1000) r a = ff
(C:$1000) x
#1 (Stop on  exec 1000)  268/$10c,  18/$12
.C:1000  E8          INX            - A:FF X:00 Y:00 SP:f7 ..-.....   11672910
(C:$1000) x
#2 (Stop on  exec e147)  268/$10c,  30/$1e
.C:e147  08          PHP            - A:FF X:01 Y:00 SP:f9 ..-.....   11672922
(C:$e147) chis 5
.C:e144  6C 14 00    JMP ($0014)    A:00 X:00 Y:00 SP:f7 ..-.....     11672903
.C:1000  E8          INX            A:ff X:00 Y:00 SP:f7 ..-.....     11672908
.C:1000  E8          INX            A:ff X:00 Y:00 SP:f7 ..-.....     11672910
.C:1001  8E 20 D0    STX $D020      A:ff X:01 Y:00 SP:f7 ..-.....     11672912
.C:1004  60          RTS            A:ff X:01 Y:00 SP:f7 ..-.....     11672916
(C:$e147) 

setting PC to new address, or using goto command (g) does this:

#1 (Stop on  exec 1000)  167/$0a7,  36/$24
.C:1000  EE 20 D0    INC $D020      - A:00 X:00 Y:00 SP:f7 ..-.....   10506861
(C:$1000) r pc = 1003
(C:$1000) x
#2 (Stop on  exec e147)  167/$0a7,  48/$30
.C:e147  08          PHP            - A:00 X:00 Y:00 SP:f9 ..-.....   10506873
(C:$e147) chis 3
.C:e144  6C 14 00    JMP ($0014)    A:00 X:00 Y:00 SP:f7 ..-.....     10506856
.C:1003  60          RTS            A:00 X:00 Y:00 SP:f7 ..-.....     10506861
.C:1003  60          RTS            A:00 X:00 Y:00 SP:f7 ..-.....     10506867
(C:$e147)

so it seems the instruction at the current (or new) address is "executed" two times (looking at the cpu history) but it is actually only really executed the second time, when this instruction is one that changes one of the registers or the PC.

also see this bug, looks like it describes the same issues:
https://sourceforge.net/p/vice-emu/bugs/2024/

Discussion

  • gpz

    gpz - 2024-05-01

    This may just be a bug in the chis feature. But yeah, its weird

     
  • gpz

    gpz - 2024-05-02

    OK first experiment shows:
    - the problem exists in both GTK and SDL version, so this isn't some weird issue related to threading (THANK GOD)
    the history is wrong, but the instruction is not actually executed twice (GOOD!)
    It IS executed twice. Bummer

     

    Last edit: gpz 2024-05-02
  • gpz

    gpz - 2024-05-02

    doesnt even need a breakpoint apparently, just "enter monitor":
    enter monitor, r a=ff, z ... last instruction will be "executed" (but not really =P)

    so somehow the order of events (enter monitor, modify registers, continue) screws it up

     
  • gpz

    gpz - 2024-05-02

    ... and it also happens in xscpu64, which doesn't have a chis implementation at all.

     
  • gpz

    gpz - 2024-05-02

    it seems to be a very old bug, and it seems NOT to be related to "cpu history". i could reproduce the first example even in the 1.9 release (which doesn't have cpu history at all)

    wth, noone noticed this, ever? :D

     

    Last edit: gpz 2024-05-02
  • gpz

    gpz - 2024-05-02

    Just so it wont get forgotten and maybe someone else can pick it up... the problem is likely related to how the registers are "exported" and "imported" before entering/after leaving the monitor. Unfortunately this is really non trivial and very old code, which is seriously lacking comments (of course, in good VICE tradition), so its hard to track down.

    It would help if we could come up with a test/example that reproduces the problem only by entering/exiting the monitor and does not involve breakpoints

    Also the instruction IS actually executed twice, which is really fatal and a big problem :(

     
  • Algorithmix

    Algorithmix - 2024-05-02

    I was just about to write a ticket on this (split out from #2024).

    This instruction-duplication can also be reproducted without "r", but with "g XXXX" and a breakpoint. For example:

    • Start a clean VICE
    • Press ALT+H to enter the monitor
    • Enter this into the monitor:
    a c000 inc $0400
    .c003  jmp $c003
    .c006  
    

    and

    break exec c003
    g c000
    
    • If you type m 0400, you can see that address $0400 contains $22 instead of $21

    • If you type cpuhistory, you can also see that it's duplicated in the CPU-history

     
     
    EDIT: It seems like you just have to SET a breakpoint, you don't have to actually break at it, for this to happen. If you instead of break exec c003 write some random address like break exec 4000, the instruction-duplication still happens after g c000.

    But if you between break exec 4000 and g c000 exit the monitor and enter it again, it doesn't happen. So it looks a bit like a breakpoint has to have been made (or touched or something) in the current monitor-session..?

     

    Last edit: Algorithmix 2024-05-02
  • robozz

    robozz - 2024-05-02

    Found this:
    - set a break point (does not even have to be enabled)
    - execute any 'r' command
    and then do a reset immediately (from the monitor)
    this will now make Vice lock up(?) (until you reset again).

    note that you can enter the monitor and you'll see that the program is still running!

     
  • gpz

    gpz - 2024-05-02

    If you can build yourself, please try this horrible patch:

    Index: src/6510dtvcore.c
    ===================================================================
    --- src/6510dtvcore.c   (Revision 45149)
    +++ src/6510dtvcore.c   (Arbeitskopie)
    @@ -421,22 +421,25 @@
             if (ik & (IK_MONITOR | IK_DMA)) {                                      \
                 if (ik & IK_MONITOR) {                                             \
                     if (monitor_force_import(CALLER)) {                            \
    -                    IMPORT_REGISTERS();                                        \
    +                    /*IMPORT_REGISTERS();*/                                        \
                     }                                                              \
                     if (monitor_mask[CALLER]) {                                    \
                         EXPORT_REGISTERS();                                        \
                     }                                                              \
                     if (monitor_mask[CALLER] & (MI_STEP)) {                        \
    +                    EXPORT_REGISTERS();                                        \
                         monitor_check_icount((uint16_t)reg_pc);                    \
                         IMPORT_REGISTERS();                                        \
                     }                                                              \
                     if (monitor_mask[CALLER] & (MI_BREAK)) {                       \
                         if (monitor_check_breakpoints(CALLER, (uint16_t)reg_pc)) { \
    +                        EXPORT_REGISTERS();                                    \
                             monitor_startup(CALLER);                               \
                             IMPORT_REGISTERS();                                    \
                         }                                                          \
                     }                                                              \
                     if (monitor_mask[CALLER] & (MI_WATCH)) {                       \
    +                    EXPORT_REGISTERS();                                        \
                         monitor_check_watchpoints(LAST_OPCODE_ADDR, (uint16_t)reg_pc); \
                         IMPORT_REGISTERS();                                        \
                     }                                                              \
    

    It seems to remove some of the problem at least (perhaps all?) - but i don't know what it might break.

     
    • Querino

      Querino - 2024-05-03

      i did try ist. and indeed it looks this "horrible hack" fixes the 3 initial posted probs, plus the other two as well. the 5 cases:


      break 1000
      break e147

      a 1000
      INC $D020
      RTS

      sys 4096

      r a = ff

      chis 4


      break 1000
      break e147

      a 1000
      INX
      STX $D020
      RTS

      sys 4096

      r a = ff

      chis 5


      break 1000
      break e147

      a 1000
      INC $D020
      RTS

      sys 4096

      r pc = 1003

      chis 5


      break 1000
      r a = ff
      reset


      a c000
      inc $0400
      jmp $c003

      break exec c003
      g c000

      m 0400
      chis 2


      seem to work as expected.
      BUT i am a complete n00b when it comes to stuff like this, i only followed the instructions.
      attached a pic of the last case.

       

      Last edit: Querino 2024-05-03
      • gpz

        gpz - 2024-05-03

        cool, that is encouraging at least :) I still have not understood why

                         if (monitor_mask[CALLER]) {                                    \
                             EXPORT_REGISTERS();                                        \
                         }  
        

        is still required after inserting the other EXPORT_REGISTERS() invocations, which is why i did not yet commit. Will look at this a bit closer then :)

         
  • gpz

    gpz - 2024-05-05

    i have comitted a more sane version of that patch in r45151 - please test, not only if the problem is solved, but also if everything related to R and G commands, and entering/exiting the monitor, still works as before :)

     
  • gpz

    gpz - 2024-08-17

    So, as a first step to get these things under control i knocked up the beginning of a test bench for the monitor: https://sourceforge.net/p/vice-emu/code/HEAD/tree/testprogs/Monitor/testbench/
    Refer to the included readme for details, how to add tests etc. Obviously more tests would be good, so feel free to provide some :)

    As for this ticket:
    - some tests are missing, some of the cases Querino posted need to be added
    - if all those pass (on trunk) then this ticket can probably be closed?

     

Log in to post a comment.