-
Notifications
You must be signed in to change notification settings - Fork 30
/
interact.mu4
215 lines (158 loc) · 6.65 KB
/
interact.mu4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
| This file is part of muforth: https://muforth.dev/
|
| Copyright 2002-2024 David Frech. (Read the LICENSE for details.)
| Support common to all 908 and S08 interactions. Things like SWI stack
| frames, reading and writing memory using "indexed" reads and writes.
loading S08 Interaction (common)
variable chatting
variable chat-vector
: chat-cmd ( index - index+1) dup cells constant 1+
does> @ chat-vector @ =if + @execute ^ then 2drop
error" Not connected to a chat-capable target" ;
: chat-fail error" Chat command not implemented" ;
0 ( initial command index)
chat-cmd t.Hello
chat-cmd t.GetRegs ( frame - sp)
chat-cmd t.SetRegs ( frame)
chat-cmd t.Run ( )
chat-cmd t.ReadChunk ( target len buf) ( XXX order??)
chat-cmd t.WriteChunk ( target len buf)
chat-cmd t.FlashChunk ( target len buf fcmd - status)
drop ( index)
: >image ['] read-host-image ( read from memory image) du-target ;
-: ( buf addr len) rot t.ReadChunk ;
: >chat [ #] ( read from connected target) du-target ;
| We keep a local copy of the target's registers in the same order as they
| appear in an exception frame.
|
| The order, low to high: H CC A X PCH PCL
6 buffer chat-frame ( local copy of SWI stack frame)
variable chat-sp ( current value of target's SP)
: get-regs chat-frame t.GetRegs chat-sp ! ;
: set-regs chat-frame t.SetRegs ;
( These index into our local chat-frame, _not_ into target memory!)
: reg ( offset) constant does> @ chat-frame + ; ( self-index)
00 reg .H
01 reg .CC
02 reg .A
03 reg .X
04 reg .PC
04 reg .PCH
05 reg .PCL
( These are handy.)
: pc! .PC beh! ;
: pc@ .PC beh@ ;
: hx! >lohi .H c! .X c! ;
: hx@ .H c@ .X c@ hilo> ;
: 4# # # # # ;
: .bits8 binary <# 4# 4# #> type ;
: .h16 hex <# 4# #> type ;
: .b ( a) c@ .h8_ ;
: .w ( a) beh@ .h16 space ;
: .regs
radix preserve
cr ." V--HINZC A H X SP PC"
cr .CC c@ .bits8 space .A .b .H .b .X .b chat-sp @ .h16 space .PC .w ;
: copy-chunk ( 'target len - 'target+len)
| cr ." copy-chunk " 2dup swap u. u.
2dup + push over image+ t.WriteChunk pop ;
: copy-region ( a len)
| cr ." copy-region " 2dup swap u. u.
256 /mod ( r q) swap push for 256 copy-chunk next
pop =if ( rem) copy-chunk drop ^ then 2drop ;
variable ram-copied ( pointer to first un-copied byte)
: copy-ram
h preserve ram
ram-copied @ dup 0= if drop region drop then
\m here over - copy-region
\m here ram-copied ! ;
( t.Hello will copy the flash code to RAM.)
: hi ram-copied off chatting on >chat t.Hello get-regs .regs
now __chatting is __meta __meta ;
: chat-via pop chat-vector ! hi ;
: run ( pc) pc! copy-ram set-regs t.Run ; ( don't wait for target)
: runwait ( pc) run get-regs ; ( wait for target)
: call ( pc) runwait .regs ;
: 'reset ( - pc) \eq Vreset image-@ ;
: reset 'reset call ; ( MSP430 version has a delay between run and get-regs)
: go 'reset run ;
| NOTE: top cell of target stack is *scratch* - so allocate it but don't
| copy it back and forth.
2 constant #scratch ( number of "scratch" bytes on top of target stack)
meta
: sp0 [ @ram #ram + #48 - #] ;
: sp! #scratch - hx! ;
: sp@ hx@ #scratch + ;
: depth \m sp0 \m sp@ - \m cell/ ;
forth
| stack> *first* builds a local image of the target stack - in the RAM
| image - and *then* copies it, in one chunk, to the target.
: stack> ( "push" stack to target)
depth 0 max 8 min ( more than that would be silly)
\m sp0 over \m cells - dup \m sp! ( top of D stack) image+ m !
for >lohi m& m& next ( copy each cell as a word to D stack)
( Now copy stack image to target)
\m sp@ dup image+ m @ over - swap t.WriteChunk ;
| stack< *first* copies the target stack, in one chunk, to the host's RAM
| image, and *then* pulls the values out and pushes them onto the host's stack.
: stack< ( "pop" stack from target)
\m depth 0 max 8 min ( more than that would be silly) =if
\m sp@ ( target) over \m cells ( len) over image+ t.ReadChunk
dup ( depth) \m sp@ image+ m ! ( do this after ReadChunk)
for m* m* hilo> pop 2push next ( starting with top, push to R)
for 2pop push next ( pop from R to reverse order) ^ then drop ;
: cont stack> runwait stack< .regs ;
-: ( cfa) ( execute target word on stack) pc! cont ; is remote
| Set |@ and |c@ to _some_ form of target fetch. Prefer to get bytes from
| target if we're connected. This word is useful so we can set an initial
| state for target's du and dis so that inspect won't crash when it
| runs |@ to get a default ea.
: >target chatting @ if >chat ^ then >image ;
| Define our own key bindings for memory dumping and disassembly. We'll
| default to host bindings if there isn't one in our array. This way we
| only have to define the "delta" between host and target behaviours.
128 array hc08-seekeys
( Default key action is to run host key code)
host-seekeys hc08-seekeys 128 cells cmove
( Support for dumping memory)
: 1dump ( a)
hex-bytes ( set field width)
>image dup .addr dup .hex-bytes
chatting @ if
-valid
>chat dup _addr dup .hex-bytes
-valid
then
drop ( a) ;
( So we can easily look at the signature embedded into the image.)
: 1dump-chars ( a)
hex-bytes
>target
dup _addr dup .chars
dup .addr dup .hex-bytes
drop ;
hc08-seekeys -1 du-mode dumping >target skip+ skip- 1dump ( a - a')
hc08-seekeys -1 du-mode dumping-chars >target skip+ skip- 1dump-chars ( a - a')
hc08-seekeys -1 du-mode disasming >target dis+ dis- 1dis ( a - a')
hc08-seekeys 'seekeys ! ( switch over to our bindings)
key: d ( a - a 0) dumping 0 ;
key: C ( a - a 0) dumping-chars 0 ; ( small c is "call")
key: i ( a - a 0) disasming 0 ;
host-seekeys 'seekeys ! ( back to host bindings)
( Interactive)
( make an alias so we can still get to host's du)
: _du du ;
| Sometimes, when chatting, we want to dump or disassemble something that
| is in RAM. If we have just compiled it, and haven't yet run any code, the
| host RAM and target RAM are out of sync; and because we show the contents
| of the target RAM when chatting, we see garbage.
|
| To improve this situation, let's copy-ram - if we're chatting and trying
| to look at the ram - before doing a dis.
: ?sync-ram ( a - a)
chatting @ if
h preserve ram
dup ram-copied @ \m here within if copy-ram then
then ;
: du ( a - a') dumping inspect ;
: dis ( a - a') ?sync-ram disasming inspect ;