home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / Mops 2.7 / Mops source / Module source / Debugmod.txt < prev    next >
Encoding:
Text File  |  1995-09-21  |  21.1 KB  |  942 lines  |  [TEXT/MSET]

  1. \ This module handles decompilation and debugging.
  2.  
  3. \ June 92    - fixed trap handling for user mode / virtual memory.
  4.  
  5. false    value    INMOD?            \ true if we're decompiling/debugging
  6.                     \ a module
  7.     objPtr    THEMOD    class_is  module
  8.                     \ This is the module we're 
  9.                     \  decompiling/debugging
  10.     handle    THEHDL
  11.  
  12.  
  13. :class    MOD-DIC-MARK    super{ dic-mark }
  14.  
  15.     var    MODCXT
  16.     var    CXTOFFS
  17.     var    MODPTR
  18.  
  19. :m DUMP:
  20.     ." modPtr:  "  get: modPtr  .h  cr
  21.     ." modCxt:  "  get: modCxt  .h  cr
  22.     ." cxtOffs: "  get: cxtOffs .h  cr  ;m
  23.  
  24. :m SELECTMOD:    \ ( ^mod -- )
  25.     -> theMod        \ Fails if not a module object pointer
  26.     load: theMod        \ Ensure module is loaded
  27.     handle: theMod  put: theHdl
  28.     nptr: theHdl  put: modPtr
  29.     get: modPtr  size: theHdl  +  32 -
  30.     dup  put: modCxt  4- @  put: cxtOffs  ;m
  31.  
  32. :m SETTOMODTOP:
  33.     #threads FOR
  34.         get: modCxt
  35.         i  2 <<  +  displace  get: cxtOffs -
  36.         i to: links
  37.     NEXT
  38.     setc: self  ;m
  39.  
  40. :m NEXTINMOD:  { \ lfa -- lfa }
  41.     get: current  at: links
  42.     dup  get: modPtr  <=  IF  drop  0  exit  then
  43.     dup -> lfa
  44.     displace  get: current  to: links
  45.     setc: self  lfa  ;m
  46.  
  47. :m FINDINMOD:  { s255 \ addr len lfa -- cfa T  |  s255 F }
  48.     s255 count  -> len -> addr
  49.     addr len upper
  50.     setToModTop: self
  51.     BEGIN
  52.         nextinMod: self  -> lfa
  53.         lfa nif  s255  false  exit  then
  54.         lfa l>name  n>count  addr len  s=
  55.         IF  ( Found it! )
  56.             lfa link>  true  exit
  57.         THEN
  58.     AGAIN  ;m
  59.  
  60. ;class
  61.  
  62. mod-dic-mark  MM
  63.  
  64. : IN
  65.     '  ( module cfa )
  66.     >obj  selectMod: MM  lock: theMod
  67.     true -> inMod?
  68.     theMod use_module  ;
  69.  
  70. : NOTIN
  71.     false -> inMod?  ;
  72.  
  73. : SET_MODBASE        \ Be awfully careful doing this!!
  74.     inMod? IF  base: theMod  32766 +  ELSE  -1  THEN
  75.     -> modbase  ;
  76.  
  77. : @ABSM  { ^rel-addr \ svModbase -- abs-addr }
  78.     modbase -> svModbase  set_modbase
  79.     ^rel-addr  @abs
  80.     svModbase -> modbase  ;
  81.  
  82. : (GET_CFA)  { \ svModbase -- cfa }
  83.     Mword dup c@ over + c@  & :  =
  84.     IF  ( method for a class )
  85.         hash  recurse            \ Recursive call to get class
  86.         chkClass
  87.         modbase -> svModbase  set_modbase
  88.         findm  nip
  89.         svModbase -> modbase
  90.     ELSE
  91.         inMod?
  92.         IF        \ in a module
  93.             findinmod: MM
  94.             nif  true abort" not found"  then
  95.         ELSE        \ in main dic
  96.             nilP -> theMod
  97.             find  0= abort" not found"
  98.         THEN
  99.     THEN  ;
  100.  
  101. : GET_CFA
  102.     (get_cfa)  ( false -> inMod? )  ;
  103.  
  104.  
  105. \        ========== DECOMPILER ==========
  106.  
  107.     0    value    LOCATION    \ Holds the current address in the parameter
  108.                             \  field of the definition being decompiled.
  109.     0    value    THIS_CFA    \ Holds the current cfa.
  110.     0    value    THAT_CFA    \ Holds the cfa called by current instruction
  111.     2    value    GIN            \ "Go in". Holds the current amount to indent.
  112.    10    value    SAVEBASE    \ Saves the number base.
  113.     0    value    #P            \ Number of named parms/local vars.
  114. false    value    CALL?        \ True if we're processing a call.
  115.     0    value    LAST_OBJ    \ The last object referenced in debugging
  116.  
  117.  
  118. : .LOCN         \ Prints the current value of LOCATION and the value of the
  119.                 \ word there.
  120.     location  6 .r  location w@  5 .r  location 2+ w@  5 .r  ;
  121.  
  122. : DIN           \ "Do indent".  Prints the location and then indents.
  123.     setFwind
  124.     cr .locn  gin spaces
  125.     location  addr>curs drop  ;
  126.  
  127. : NXT>        \ ( -- n )  Fetches the longword where LOCATION points, and
  128.             \           updates LOCATION.
  129.     location w@  2 ++> location  ;
  130.  
  131. : .NO
  132.     dup .  dup  decimal .  hex
  133.     bl & ~  within? if  emit  else  drop  then  ;
  134.  
  135. : .1    1 .r  ;
  136.  
  137. : .D    4 7  within?
  138.     IF  ." parm/loc# "  7 swap -  .1  EXIT  THEN
  139.     dup 3 =  IF  drop  ." i"  EXIT  THEN
  140.     ." D"  .1  ;
  141.  
  142. : .A    case[       5  ]=>  ." MP"
  143.         [  6  ]=>  ." SP"
  144.         [  7  ]=>  ." RP"
  145.         default=>  ." A"  .1
  146.     ]case  ;
  147.         
  148. : STRING?
  149.     that_cfa 2- w@x  -18 =  ;
  150.  
  151. : .NAME  { cfa -- }
  152.     cfa  .id
  153.     call?  0EXIT
  154.     cfa  ['] (defer)  =
  155.     if  4 ++> location  exit  then
  156.     string?
  157.     if    space  & " emit  location count 2dup type  & " emit
  158.         +  align  -> location
  159.     then  ;
  160.     
  161. : ?.PARAMETERS    \ ( cfa -- )  Prints any parameters associated with 
  162.             \   this word.
  163.     drop  ;
  164.  
  165. : ?.VALUE     \ ( cfa -- )  Prints a value or any other useful (?) 
  166.         \  information associated with this word.
  167.     drop  ;
  168.  
  169.  
  170. : .WORD     \ ( cfa -- )  Prints the name of the word with the given cfa.
  171.     ( ?mcf )  dup  .name  dup ?.parameters  ?.value  ;
  172.  
  173. : SHOW_CLASS  { addr \ svModbase -- }
  174.     modbase -> svModbase
  175.     set_modbase
  176.     addr >obj  .class: object
  177.     svModbase -> modbase  ;
  178.  
  179. : ?TYP  { addr -- addr }
  180.     addr 2- w@x
  181.     case[       objCode  ]=>    ." object of type "  addr show_class
  182.         [  valCode  ]=>    ." value "  addr @  .no
  183.         default=>  drop
  184.     ]case  ;
  185.  
  186. local  IDENTIFY?  { \ svModbase op mode reg reg1 disp incr -- b }
  187.  
  188. : GETMODE®
  189.     op  $ 7  and  -> reg
  190.     op  $ 38 and  3 >>  -> mode  ;
  191.  
  192. : GETADDR        \ ( -- addr )
  193.     getMode&Reg
  194.     mode 5 =  nif  0  exit  then    \ If not d(An), just rtn zero
  195.     reg                    \ Reg
  196.     case[       3    ]=>    lobase
  197.         [  4    ]=>    hibase
  198.         [  5    ]=>    theMod nilP <>
  199.             if    base: theMod  32766 +
  200.             else    0
  201.             then
  202.         default=>    drop  0
  203.     ]case
  204.     location w@x  +            \ Add displ
  205.     2 ++> location  ;
  206.  
  207. : d(An)    getAddr
  208.     reg 2 =
  209.     if    ." ivar offs "  .
  210.     else    cfa? if  dup .id space  then  dup  .h  ?typ
  211.     then  ;
  212.  
  213. : TRYLIT
  214.     reg 4 <>  ?exit
  215.     location @  decimal . hex  4 ++> location  ;
  216.  
  217. : .ADDR
  218.     getMode&Reg
  219.     mode
  220.     case[       0  ]=>        reg .d
  221.         [  1  ]=>        reg .a
  222.         [  2  ]=>    ." ("    reg .a  ." )"
  223.         [  3  ]=>    ." ("    reg .a  ." )+"
  224.         [  4  ]=>    ." -("    reg .a  ." )"
  225.         [  5  ]=>    d(An)
  226.         [  7  ]=>    tryLit
  227.         default=>  drop
  228.     ]case  ;
  229.  
  230. : SEE_CASE    ;
  231.  
  232. : DO_JSR
  233.     call?  IF  ." JSR "  else  ." JMP "  THEN
  234.     getAddr  dup -> that_cfa  .name
  235. \    that_cfa  ['] (case)  =  IF  see_case  THEN
  236. ;
  237.  
  238. : DO_BSR
  239.     ." BSR "
  240.     op $ FF and  -> disp  0 -> incr
  241.     disp 0=
  242.     if    location w@x  -> disp  2 -> incr
  243.     else    disp  $ 7F > if  $ FFFFFF00  or> disp  then
  244.     then
  245.     disp location +  dup -> that_cfa  .name
  246.     incr ++> location  ;
  247.  
  248. : DO_BCC
  249.     ." BRANCH"
  250.     op  $ FF  and
  251.     nif  2 ++> location  then  ;
  252.  
  253. : DO_LONG#
  254.     location @  .no
  255.     4 ++> location  ;
  256.  
  257. : DO_SHORT#
  258.     op $ FF and  .no
  259.     2 ++> location  ;
  260.  
  261. : DO_LEA
  262.     op  $ E00 and 9 >>  -> reg1
  263.     op  $ 41D2  = if  ." self"  exit  then
  264.     reg1
  265.     NIF    getAddr
  266.         reg 2 =
  267.         if      ." ivar offs "  .
  268.         else      ." object "  dup -> last_obj  8 -  .name
  269.         then
  270.     ELSE
  271.         ." LEA  "  .addr  ."   ->  "  reg1 .a
  272.     THEN  ;
  273.  
  274. : DO_MOVE
  275.     ." MOVE  "  .addr  ."  -> "
  276.     op  3 >>  $ 38 and
  277.     op  9 >>  $  7 and  or  -> op  .addr  ;
  278.  
  279. : 1OP        \ ( addr len )
  280.     type  2 spaces  .addr  ;
  281.  
  282. : DO_ADDQ
  283.     op  $ 100 and  nif  ." ADDQ #"  else  ." SUBQ #"  then
  284.     op  9 >>  7 and
  285.     dup nif  drop 8  then  .
  286.     ." ,"  .addr  ;
  287.  
  288. : DO_MOVEM
  289.     op  $ FF00 and  $ 4800 =
  290.     if    ." MOVEM  regs,"  .addr
  291.     else    ." MOVEM  "  .addr  ." ,regs
  292.     then
  293.     2 ++> location  ;
  294.  
  295. : DO_+ETC
  296.     op  $ F000  and
  297.     case[       $ D000    ]=>    ." ADD  "    true
  298.         [  $ 9000    ]=>    ." SUB  "    true
  299.         [  $ C000    ]=>    ." AND  "    true
  300.         [  $ 8000    ]=>    ." OR  "    true
  301.         [  $ B000    ]=>    op $ 100 and
  302.                 if ." XOR  " else ." CMP  " then   true
  303.         default=>    drop  ." trap "  op .h  false
  304.     ]case
  305.     0exit
  306.     op 9 >> 7 and  -> reg1
  307.     op  $ 100 and
  308.     if    reg1 .d  ."  -> "  .addr
  309.     else    .addr  ."  -> "  reg1 .d
  310.     then  ;
  311.  
  312. : DO_IMM
  313.     op  8 >>  $ F  and
  314.     case[       0  ]=>    ." OR"
  315.         [  2  ]=>    ." AND"
  316.         [  4  ]=>    ." SUB"
  317.         [  6  ]=>    ." ADD"
  318.         [ $ A ]=>    ." XOR"
  319.         default=>    " ???"
  320.     ]case
  321.     op 6 >> 3 and
  322.     case[      0 ]=>    ." .B  "  location w@x  2 ++> location
  323.         [ 1 ]=>    ." .W  "  location w@x  2 ++> location
  324.         default=>    ." .L  "  location  @   4 ++> location
  325.     ]case
  326.     ." #"  .h  ."  -> "  .addr  ;
  327.  
  328. :loc IDENTIFY?
  329.     true
  330.     location w@  -> op  2 ++> location
  331.     false -> call?  0 -> that_cfa
  332.  
  333.     op  $ FFC0 and  $ 4E80 =    if  true -> call?  do_jsr
  334.                             exit  then
  335.     op  $ FFC0 and  $ 4EC0 =   ( JMP)  if  do_jsr    exit  then
  336.     op  $ FF00 and  $ 6100 =    if  true -> call?  do_bsr
  337.                             exit  then
  338.     op  $ F000 and  $ 6000 =    if  do_bcc    exit  then
  339.     op  $ 29BC  =            if  do_long#    exit  then
  340.     op  $ FF00 and  $ 7400 =    if  do_short#    exit  then
  341.     op  $ 2D16 =            if  ." DUP"    exit  then
  342.     op  $ F000 and  $ 2000 =    if  do_move    exit  then
  343.     op  $ 4E75  =            if  ." EXIT"    exit  then
  344.     op  $ 588E  =            if  ." DROP"    exit  then
  345.     op  $ F000 and  $ 5000 =    if  do_addq    exit  then
  346.     op  $ F1C0 and  $ 41C0 =    if  do_lea    exit  then
  347.     op  $ FF00 and  dup  $ 4800 =  swap  $ 4C00 =  or
  348.                     if  do_movem    exit  then
  349.     op  12 >>  8  $ D  within? nip  if   do_+etc    exit  then
  350.     op  $ F000 and            nif do_imm    exit  then
  351.     op  $ FF00 and
  352.     case[        $ 4200    ]=>    " CLR"  1op
  353.         [    $ 4A00    ]=>    " TST"  1op
  354.             default=>    2drop  false
  355.     ]case
  356. ;loc
  357.     
  358.  
  359. : .INST        \ Decompiles the next instruction in the current definition.
  360.     din
  361.     identify? drop  ;
  362.  
  363.  
  364.     0    value    CL_DEPTH
  365.  
  366. : CRI        \ CR plus indent
  367.     cr  cl_depth 2+  spaces  ;
  368.  
  369. getSelect PRINT:        constant   printID
  370.  
  371. : .IVLIST  { ^obj ^class \ svModbase thisivar ioffs ^cl -- }
  372.     ^class ifa displace  -> thisivar
  373.     BEGIN
  374.         thisivar @ 0>=
  375.         IF            \ Traverse n-way for superclasses
  376.             BEGIN    thisivar @  0EXIT
  377.                 thisivar @absM -> ^cl
  378.                 cri  ." superclass "
  379.                 ^cl .id
  380.                 ^cl  ['] object  =
  381.                 NIF    2 ++> cl_depth
  382.                     ^obj ^cl  recurse
  383.                     2 --> cl_depth
  384.                 THEN
  385.                 4 ++> thisivar
  386.             AGAIN
  387.         ELSE            \ Ordinary ivar
  388.             thisivar 8 + @absM  -> ^cl
  389.             cri thisivar 12 + w@ -> ioffs
  390.             ." ivar offset "  ioffs .
  391.             ^cl  ['] object  =
  392.             IF    ."    (bytes)"
  393.             ELSE    ." class "  ^cl .id  2 spaces
  394.                 ^obj ioffs +  printID ^cl
  395.                 modbase -> svModbase  set_modbase
  396.                 findm
  397.                 svModbase -> modbase
  398.                 >r + r>  ex-method
  399.             THEN
  400.             thisivar 4+ displace  -> thisivar
  401.         THEN
  402.     AGAIN  ;
  403.  
  404. : .SUPERS  { ^class \ svModbase thisivar ^cl -- }
  405.  
  406. \ This code is similar to .IVARS above, since we find the superclasses by traversing the ivar chain to find the n-way for the supers.  But of course we don't print any ivar information.
  407.  
  408.     ^class ifa displace  -> thisivar
  409.     begin
  410.         thisivar @ 0>
  411.         if            \ Traverse n-way for superclasses
  412.             begin    thisivar @  0exit
  413.                 thisivar @absM -> ^cl
  414.                 cri  ." superclass "
  415.                 ^cl .id
  416.                 ^cl  ['] object  =
  417.                 nif    2 ++> cl_depth
  418.                     ^cl  recurse
  419.                     2 --> cl_depth
  420.                 then
  421.                 4 ++> thisivar
  422.             again
  423.         else            \ Ordinary ivar
  424.             thisivar 8 + @absM  -> ^cl
  425.             thisivar 4+ displace  -> thisivar
  426.         then
  427.     again  ;
  428.  
  429. ' null    vect    VV
  430.  
  431. local .WHATEVER  { cfa \ ^obj svModbase -- b }
  432.  
  433. : .OBJECT
  434.     cfa ?typ  2 spaces
  435.     modbase -> svModbase  set_modbase
  436.     cfa >obj -> ^obj        \ Note: we've altered modbase, but
  437.     print: [ ^obj ]            \ it's OK here since none of these
  438.     ^obj dup >class            \ words are local to this module.
  439.     svModbase -> modbase
  440.     0 -> cl_depth
  441.     .ivlist  ;
  442.  
  443. : .CLASS
  444.     ." Class "  cfa  dup  .id  .supers  ;
  445.  
  446. : .DEFN    ;
  447.  
  448. : .VALUE        cfa ?typ  ;
  449.  
  450. : .VECT
  451.     ." Vect -> "
  452.     4 ++> cfa            \ Step past JSR doVect
  453.     cfa @ nif
  454.         4 ++> cfa  ." default: "
  455.         location  cfa -> location  identify? drop  -> location
  456.     else    cfa @abs  .id
  457.     then  ;
  458.  
  459.  
  460. :loc .WHATEVER        \ { cfa -- b }
  461.     cfa 2- w@x
  462.     case[       objcode            ]=>  .object  false
  463.         [  classcode            ]=>  .class   false
  464.         [  ' .inst    2 - w@x    ]=>  .defn    true
  465.         [  ' location 2 - w@x    ]=>  .value   false
  466.         [  ' vv       2 - w@x    ]=>  .vect    false
  467.         default=> ." ???"  drop  false
  468.     ]case
  469. ;loc
  470.  
  471. : START  { cfa \ ok? -- ok? }    \ Sets things up for a new decompilation.
  472.                                 \   Returns true if we are to continue.
  473.     true -> ok?
  474.     cfa -> location
  475. \    location  locate_src
  476.     2 ++> gin  din
  477.     ." : "  cfa dup .id  >name  c@ 64 and if ."  IMMEDIATE"  then
  478.     ok?
  479.     if    cfa  -> location
  480.     else  ( back to where we were )
  481.         -> location  -2 ++> gin
  482.     then
  483.     ok?  ;  
  484.  
  485. : FINISH
  486.     -2 ++> gin
  487.     gin if  location locate_src  then  ;
  488.  
  489. : DONE?   ( -- b )
  490.     location w@  $ 4E75  =
  491.     drop false  ;
  492.  
  493.  
  494. : (SEE)  { cfa \ svBase svLocation next? stop? -- }
  495.             \ Exported.  Decompiles the word with the given cfa.
  496.     base -> svbase  hex
  497.     cfa locate_src
  498.     setFwind
  499.     cfa .whatever  IF  cfa start  ELSE  false  THEN
  500.     NIF  svbase -> base  EXIT  THEN
  501.     location @ -> this_cfa  .inst
  502.     BEGIN
  503.         true -> next?  false -> stop?    \ Do it unless we find out 
  504.                                         \  otherwise
  505.         key  & a  & z  within? if  bl -  then
  506.         case[    & Q    ]=>  sp0 sp!  svbase -> base
  507.                         notin cl  cr  quit
  508.             [  13    ]=>  location -> svLocation
  509.                         that_cfa  if  2 spaces  that_cfa  (see)  then
  510.                         svLocation -> location
  511.             [ & U    ]=>  true -> stop?  false -> next?
  512.             [ & 2    ]=>  2 ++> location
  513.             [ & P    ]=>  8 --> location
  514.             [ $ 1E    ]=>  1up  false -> next?
  515.             [ $ 1F    ]=>  1dn  false -> next?
  516.             [ $ 1C    ]=>  1Lft false -> next?
  517.             [ $ 1D    ]=>  1rt  false -> next?
  518.             [ $ 37    ]=>  home false -> next?
  519.             [ $ 31    ]=>  end  false -> next?
  520.             [ $ 39    ]=>  defnUp  false -> next?
  521.             [ $ 33    ]=>  defnDn  false -> next?
  522.             default=>  drop
  523.         ]case
  524.         next? if  location @ -> this_cfa  .inst  then
  525.         done? stop? or
  526.     until
  527.      ( Show last word )  next? IF  .inst  THEN  finish
  528.     svbase -> base  ;
  529.  
  530.  
  531. : SEE    0 -> gin  get_cfa  (see)  ;
  532.  
  533.  
  534. \            =======  DEBUGGER  =======
  535.  
  536.  
  537.      variable    PROGREGS    64 allot
  538.  
  539.     0    value    CURRMODBASE
  540.  
  541.    10    array    PCSTK
  542.     0    value    PC#
  543.  
  544.     0    value    PC            \ Current user PC on brkpt or trace trap
  545.     0    value    STATUS            \ Current user status word ditto
  546.  
  547.     0    value    BP            \ Current breakpoint address
  548.     0    value    BPCONT            \ Contents of that location
  549.  
  550.     0    value    IBP            \ Initial breakpoint address
  551.     0    value    IBPCONT        \ Contents
  552.  
  553.     0    value    TTRAPVAL        \ Original contents of T trap vector
  554.  
  555. false    value    DONE?
  556. false    value    GETOUT?
  557. false    value    INITIALIZED?
  558. false    value    IN_CASE?
  559. false    value    DEBUG_STARTED?
  560.  
  561.  
  562. : PUSHPC        PC# to: PCstk  1 ++> PC#  ;
  563.  
  564. : POPPC        -1 ++> PC#  PC# at: PCstk  ;
  565.  
  566. : BPON        \ ( addr -- )
  567.     -> BP
  568.     BP w@  -> BPcont
  569.     $ 4E40  BP w!  patches_done  ;
  570.  
  571. : BPOFF        BPcont  BP w!  patches_done  ;
  572.  
  573. :code TOPROG    \ Returns to the user prog with tracing off.
  574.     loc
  575.     movem    dic[progRegs],d0-d7/a0-a6
  576.     move.l    rel[PC],-(a7)   ; A5 won't be right for debugmod
  577.     move.w    2(rel[status]),ccr
  578.     rts
  579. ;code
  580.  
  581.  
  582. : UP        \ End tracing current definition; resume next level up.
  583.     PC# if    cr ." *** going up ***"
  584.         popPC  BPon  true -> getout?
  585.     else    cr ." *** at top already - maybe do a G instead? ****
  586.     then  ;
  587.  
  588. : DOWN
  589.     cr ." *** going down ***"
  590.     location  pushPC  ;
  591.  
  592.  
  593. : X    (lit-str) 99 ;        \ A dummy definition - not executed
  594.  
  595. : STEP_CASE
  596.     true -> in_case?  ;    \ Inhibits display till we get into the stub
  597.  
  598. : NXT_CASE    \ ( -- b )
  599.     location w@  $ 4ED1 =
  600.     if  cr ." *** doing CASE[ selection:"  false  exit  then
  601.     location w@  $ 4EF0 =
  602.     if  cr ." *** doing SELECT{ selection:"  false  exit  then
  603.     true  ;
  604.  
  605. : STEP
  606.     call?  0exit        \ If not a call, continue normal trace
  607.     that_cfa
  608.     case[      ' @(ip)    ]=>    4 ++> location  true
  609.         [ ' w@(ip)    ]=>    2 ++> location  true
  610. \        [ ' (case) ], [ ' (sel) ]=>    step_case  false
  611.         default=>    drop  true
  612.     ]case
  613.     0exit
  614.     location  BPon  true -> getout?  ;
  615.  
  616. : .DEPTH
  617.     ."   (" depth 2 .r  ." )"  ;
  618.  
  619. : .STK  { \ svCurs -- }
  620.     depth  0<=  ?exit
  621.     curs -> svCurs  -curs  20 out -  spaces
  622.     0  depth 4 min  2-
  623.     do
  624.         i pick  8 .r
  625.     -1 +loop
  626.     svCurs -> curs  ;
  627.  
  628. : .RG    \ ( addr -- )
  629.     @ 0  <#  # # # # # # # #  #>  type  ;
  630.  
  631. : .D&A  { cnt -- }
  632.     & D emit  cnt .  3 spaces
  633.     cnt 4* progRegs +  dup  .rg  10 spaces  32 +
  634.     & A emit  cnt .  3 spaces
  635.     .rg  ;
  636.  
  637. : .REGS
  638.     base  hex
  639.     8 0 do   cr  i  .d&a   loop
  640.     -> base  ;
  641.  
  642.  
  643. false    value    RES?
  644.  
  645. : *OK    & * emit  ok  ;
  646.  
  647. : DO_F  { \ svState svCurs -- }
  648.     cr OK  state -> svState  curs -> svCurs  +curs
  649.     begin    0 -> state  false -> res?
  650.         query  interpret  *OK
  651.         res?
  652.     until
  653.     svState -> state  svCurs -> curs  ;
  654.  
  655. : RESUME
  656.     true -> res?  ;
  657.  
  658. : UNBUG
  659.     initialized?  0exit
  660.     notin  cl
  661.     BPoff  TtrapVal if  TtrapVal  $ 24  !  then
  662.     false -> initialized?
  663.     drop: debugmod  ;
  664.  
  665.  
  666. ' null vect    SHOWME
  667.  
  668. : SHOW        \ ( cfa -- )
  669.     -> showme  ;
  670.  
  671. local  DISPLAY  { \ svBase svCurs svLoc next? reDisp? -- }
  672.  
  673. : DISP1
  674.     setFwind
  675.     cr  0 -> out  -curs
  676.     .locn  2 spaces  identify?  drop
  677.     40 out -  dup 0<
  678.     IF  drop  cr  0 -> out  40  then  spaces
  679.     .depth  .stk  
  680.     BEGIN
  681.         true -> next?  false -> reDisp?
  682.         key  & a  & z  within? if  bl -  then
  683.         case[      & N    ]=>  true -> done?
  684.                     BPoff
  685.                     iBP -> BP  iBPcont -> BPcont
  686.             [ & G    ]=>  true -> done?  true -> getout?
  687.                     BPoff TtrapVal  $ 24  !
  688.                     cr decimal  svCurs -> curs
  689.             [ & Q    ]=>    cr  decimal  svCurs -> curs
  690.                     unbug  quit
  691.             [ & F    ]=>  do_F
  692.                     true -> reDisp?  svLoc -> location
  693.             [ & R    ]=>  .regs  false -> next?
  694.             [ & O    ]=>  last_obj ?dup
  695.                     if  dump: **  then
  696.                     false -> next?
  697.             [ & S    ]=>  showme  false -> next?
  698.             [ 13 ],  [ & D ]=>       down
  699.             [ & U    ]=>  up
  700.             [ $ 1E    ]=>  1up  false -> next?
  701.             [ $ 1F    ]=>  1dn  false -> next?
  702.             [ $ 1C    ]=>  1Lft false -> next?
  703.             [ $ 1D    ]=>  1rt  false -> next?
  704.             [ $ 37    ]=>  home false -> next?
  705.             [ $ 31    ]=>  end  false -> next?
  706.             [ $ 39    ]=>  defnUp  false -> next?
  707.             [ $ 33    ]=>  defnDn  false -> next?
  708.             default=>  drop  step
  709.         ]case
  710.         next?
  711.     UNTIL  ;
  712.  
  713.  
  714. :loc DISPLAY    \ { \ svBase svCurs svLoc next? reDisp? -- }
  715.     debug_started?
  716.     NIF  ( selectDW  select: fWind )  true -> debug_started?  THEN
  717.     in_case?
  718.     IF    nxt_case  dup -> in_case?  EXIT  THEN
  719.     base -> svBase  hex  curs -> svCurs  -curs
  720.     false -> done?  false -> getout?
  721.     location -> svLoc
  722.     location  addr>curs drop
  723.     BEGIN    location @  -> this_cfa
  724.         disp1
  725.         reDisp?
  726.     NUNTIL  ;loc
  727.  
  728. :code  FIXMODE
  729.     move    A5,dic[tempA5]
  730.     move    rel[currModbase],A5
  731.     movem    d0-d7/a0-a6,dic[progRegs]
  732.     move    dic[tempA5],52(dic[progRegs])
  733.     move.l    6(a7),dic[PC]
  734.     move.w    4(a7),2(dic[status])
  735.     move.l    (a7)+,2(a7)
  736.     bclr    #7,(a7)
  737.     rte
  738. ;code
  739.  
  740. :code  BPTLOC    \ We come here on a breakpoint trap
  741.     bsr    rel[fixMode]
  742.     subq    #2,dic[PC]    ; Replace instrn at bkpt and
  743.     move    dic[PC],a0    ; don't forget to execute it!
  744.     move.w    2(dic[BPcont]),(a0)
  745.     jsr    dic[patches_done]
  746.     move    a0,dic[location]    ; This is location for display
  747.     bsr    dic[display]    ; display everything
  748.     dc.w    $4E42    ; TRAP 2 to set T bit & rtn
  749. ;code
  750.  
  751. :code TRACELOC
  752.     bsr    rel[fixMode]
  753.     tst    dic[done?]
  754.     bne.s    done
  755.     move    dic[PC],dic[location]   ; Next instrn is locn for displ
  756.     bsr    dic[display]
  757.     tst    dic[getout?]
  758.     bne    dic[toProg]
  759.     dc.w    $4E42    ; TRAP 2 to set T bit & rtn
  760.  
  761. done    jsr    dic[cr]    ; DONE? set - we're handling
  762.     move.l    #10,dic[base]    ;  it the next time in, so
  763.     move    dic[BP],a0    ;  the BP gets replaced.
  764.     move.w    #$4E40,(a0)    ; Replace BP for next time
  765.     jsr    dic[patches_done]
  766.     bra    dic[toProg]
  767. ;code
  768.  
  769. :code  TON        \ Returns to user's prog with tracing on.
  770.         \ We set the TRAP 2 vector pointing here, since
  771.         \ we need to be in supervisor mode to set the T bit.
  772.     movem    dic[progRegs],d0-d7/a0-a6
  773.     move.l    rel[PC],2(a7)
  774.     move.w    2(rel[status]),(a7)
  775.     bset    #7,(a7)
  776.     rte
  777. ;code
  778.  
  779.  
  780. : DEBUG        \ Exported.
  781.     0 -> PC#  false -> debug_started?
  782.     get_cfa  dup  locate_src
  783.     initialized?
  784.     nif    lock: debugMod        \ We must be locked since we'll
  785.         modbase -> currModbase    \  be called from a trap
  786.         ['] bptLoc  $ 80 !    \ We use TRAP #0 as our debug brkpt
  787.         ['] Ton     $ 88 !    \ We use TRAP #2 to turn T bit on
  788.         $ 24 @  -> TtrapVal    \ Save T trap vector (-> Macsbug?)
  789.         ['] traceLoc  $ 24 !    \ and set it to our routine TraceLoc
  790.         true -> initialized?
  791.     then
  792.     ( cfa )  BPon
  793.     BP -> iBP  BPcont -> iBPcont        \ Save initial BP details
  794. ;
  795.  
  796. \            ========  PROFILER  =========
  797.  
  798.     0    value    LINECNT
  799.     0    value    PRFPTR
  800.     0    value    LAST_PRFPTR
  801.     0    value    SRC_POS
  802.     0    value    SRC_LIM
  803.  
  804.     string+  $PRF
  805.     string+  $SRC
  806.  
  807.  
  808. : ADDR>PRF  { addr \ offs -- }
  809.     addr filestart_dp -  -> offs
  810.     reset: $prf
  811.     BEGIN
  812.         len: $prf  0<=  ?EXIT
  813.         ^1st: $prf  w@  offs =  ?EXIT        \ If found
  814.         14 skip: $prf  1 ++> lineCnt
  815.     AGAIN  ;
  816.  
  817.  
  818. : FIND_DEFN_START  { addr -- }
  819.     0 -> lineCnt
  820.     addr  addr>prf
  821.     <step: $prf  delete: $prf
  822.     addr  addr>curs  dup >pos: $src  >lim: $src  ;
  823.  
  824. : FIND_DEFN_END  { \ offs addr -- }
  825.     reset: $prf  len: $prf  0EXIT
  826.     ^1st: $prf  w@  -> offs        \ Initial offset
  827.     14 skip: $prf            \ Skip line where defn starts
  828.     BEGIN
  829.         len: $prf  0EXIT
  830.         ^1st: $prf  -> addr
  831.         addr w@  offs  >
  832.         IF  addr w@ -> offs  ELSE  true  addr 5 + c!  THEN
  833.         addr 4+ c@  ?EXIT
  834.         14 skip: $prf
  835.     AGAIN  ;
  836.  
  837.  
  838. : COUNT_THIS  { addr -- }
  839.     addr addr>prf  ^1st: $prf  -> prfPtr
  840.     len: $prf  0EXIT
  841.     prfPtr 2+ w@  addr w!        \ Replace instruction at breakpoint
  842.     patches_done
  843.     1  prfPtr 6 +  +!            \ Increment execution count
  844.     last_time                    \ Increment time
  845.     IF    now last_time -  last_prfPtr 10 +  +!
  846.     THEN
  847.     prfPtr -> last_prfPtr  ;
  848.  
  849.  
  850. :code PRFLOC        \ We come here on a profile trap
  851.         push    glob[ticks]
  852.         move    A5,dic[tempA5]
  853.         move    rel[currModbase],A5
  854.         pop        dic[now]
  855.         movem    d0-d7/a0-a6,dic[progRegs]
  856.         move    dic[tempA5],52(dic[progRegs])
  857.         move.l    2(a7),dic[PC]
  858.         move.w    (a7),2(dic[status])
  859.         lea        continue,a0
  860.         move.l    a0,2(a7)
  861.         bclr    #7,(a7)
  862.         rte
  863.  
  864. continue subq    #2,dic[PC]
  865.         move    dic[PC],a0
  866.         move    a0,dic[this_BP]
  867.         push    a0
  868.         bsr        dic[count_this]
  869. \        lea        dic[prfloc],a0
  870. \        move    a0,$24
  871.         dc.w    $4E42            ; TRAP 2 to set T bit & rtn
  872. ;code
  873.  
  874. :code PRFTRACE        ; Now we've executed the inst at bkpt
  875.         bsr        rel[fixMode]
  876. \        move    dic[ttrapval],$24
  877. \        call    debugger
  878.         move    dic[this_BP],a0
  879.         move.w    #$4E41,(a0)
  880.         jsr        dic[patches_done]
  881.         movem    dic[progRegs],D0-D7/A0-A6
  882.         move.l    rel[PC],-(a7)        ; Set up for RTS
  883.         move.l    glob[ticks],dic[last_time]
  884.         move.w    2(rel[status]),ccr
  885.         rts
  886. ;code
  887.  
  888.  
  889. : SET_BRKPTS  { \ addr -- }
  890.     reset: $prf
  891.     BEGIN
  892.         len: $prf  NIF  patches_done  EXIT  THEN
  893.         ^1st: $prf  5 + c@
  894.         NIF
  895.             ^1st: $prf w@  filestart_dp +  -> addr
  896.             addr w@  ^1st: $prf 2+ w!
  897.             $ 4E41  addr w!
  898.         THEN
  899.         14 skip: $prf
  900.     AGAIN  ;
  901.  
  902.  
  903. : PROFILE  { \ cfa -- }
  904.     lock: debugMod                \ We'll be entering via traps!
  905.     modbase -> currModbase
  906.     ['] prfLoc  $ 84 !            \ We use TRAP #1 as our profile brkpt
  907.     $ 24 @  -> TtrapVal            \ Save T-bit trap vector
  908. \    ['] prfTrace  $ 24 !        \ and reset it to point to PrfTrace
  909.     ['] Ton       $ 88 !        \ We use TRAP #2 to turn T bit on
  910.     true -> initialized?
  911.     get_cfa -> cfa   cfa locate_src
  912.     prof_str  ->: $src  ->: $prf
  913.     size: $prf  0= ?error 188    \ No log file found - needed for profile
  914.     cfa  find_defn_start
  915.     find_defn_end
  916.     delete: $prf
  917.     set_brkpts
  918.     reset: $prf  lock: $prf  ;
  919.  
  920.  
  921. : SHOWP  { \ addr loc -- }
  922.     reset: $prf  cl
  923.     ."   exec   ticks"  cr 0 -> out
  924.     BEGIN
  925.         len: $prf
  926.     WHILE
  927.         ^1st: $prf  -> addr
  928.         addr 5 + c@
  929.         NIF
  930.             addr w@  filestart_dp +  -> loc
  931.             addr 2+ w@  loc w!
  932.             addr  6 + @  ?dup
  933.             IF
  934.                 6 .r  addr 10 + @  8 .r
  935.             THEN
  936.         THEN
  937.         18 out -  spaces
  938.         nextline?: $src  IF  get: $src  type  cr  0 -> out  THEN
  939.         14 skip: $prf
  940.     REPEAT
  941.     unbug  ;
  942.