-
Notifications
You must be signed in to change notification settings - Fork 0
/
fa430.fs
473 lines (351 loc) · 14.7 KB
/
fa430.fs
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
\ FORTH Assembler for TI MSP430x2xx Family
\ Simple Assembler for Texas Instruments MSP430 Microcomputers
\ made with gforth 0-7-0 on MacOSX 10.4.11 PowerPC G4.
\ See:
\ MSP430x2xx Family User's Guide
\ SLAU144HâDecember 2004âRevised April 2011, S. 64, CPU.
\ © 2004â2011, Texas Instruments Incorporated
\ Basic Syntax
\ Put source item on data stack, followed by source adressmode modifier word.
\ Put destination item on data stack, followed by destination adressmode modifier word.
\ The mnemonic opcode word finaly compiles the Instruktion, using mode, source and destination information.
\ Assembler Forth Assembler
\ MOV r1,r2 r1 sRn r2 dRn MOV,
\ AND #0AA55h,TOM $0AA55 s#N TOM dADDR AND,
\ Autor: Michael Kalus (mk)
: .. bye ;
: %% 2 base ! ;
HERE
vocabulary msp430assembler msp430assembler definitions
true constant testing
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
testing [if]
\ *** target test memory ( adr == tstart + tadr )
create tstart $3F00 allot \ 16Kbyte
here constant tend
: tclear tstart tend over - 0 fill ; tclear
variable tdp 0 tdp !
: there tdp @ ;
0 value loca \ last opcode address. ( .lst .chk gesetzt mit [op] )
defer [op]
: setloca ( -- ) there to loca ; ( startcode, op, )
: X_c@ ( tadr -- c ) tstart + c@ ;
: X_c! ( n tadr -- ) tstart + c! ;
: X_c, ( n -- ) there X_c! 1 tdp +! ;
\ Big endian 16Bit
\ : X_@ { adr -- w } adr X_c@ 8 lshift adr 1+ X_c@ + ;
\ : X_! { w adr -- w } w 8 rshift adr X_c! w adr 1+ X_c! ;
\ : X_, { w -- } w 8 rshift X_c, w X_c, ;
\ : X_. ( w -- ) hex. ;
\ Little endian 16Bit
: X_@ { adr -- w } adr 1+ X_c@ 8 lshift adr X_c@ + ;
: X_! { w adr -- w } w 8 rshift adr 1+ X_c! w adr X_c! ;
: X_, { w -- } w X_c, w 8 rshift X_c, ;
: X_. { w -- } w $00FF and 8 lshift w $FF00 and 8 rshift or hex. ;
[then]
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ *** collect data for cross compiling
0 value mode \ addressmode mask
0 value src \ source
0 value dst \ destination
false value sflag
false value dflag
: reset-mode 0 to mode ;
: reset-src false to sflag ;
: reset-dst false to dflag ;
: set-src true to sflag ;
: set-dst true to dflag ;
: src, ( -- ) sflag if src X_, then reset-src ;
: dst, ( -- ) dflag if dst X_, then reset-dst ;
: op@ ( -- op ) loca X_@ ; ( wird gar nicht benutzt)
: op! ( op -- ) loca X_! ; ( wird gar nicht benutzt)
: op, ( op -- ) [op] X_, reset-mode ; ( formI,II,III, reti)
testing [if] ' setloca is [op] [else] ' nop is [op] [then]
\ *** Addressing modes
\ Adressing modes patch opcode befor opcode is compiled.
\ They patch the As or Ad bits and source and/or register bits.
: >sreg ( rn -- ) %1111 and 8 lshift mode or to mode ;
: >dreg ( rn -- ) %1111 and mode or to mode ;
: s>16 ( n -- n16 ) \ convert single precission to 16bit 2-complement.
dup %1111111111111111 and swap 0< if %1000000000000000 or then ;
: src-adr-offset ( adr -- 16bit-pc-offset ) there - 2 - s>16 ;
: dst-adr-offset ( adr -- 16bit-pc-offset ) there - 4 - s>16 ;
\ patch mode bits
\ set bit4,5 %0000000000xx0000 or
\ clear bit4,5 %1111111111xx1111 and
\ set bit7 %0000000010000000 or
\ clear bit7 %1111111101111111 and
: 00As ( -- ) mode %1111111111001111 and to mode ;
: 01As ( -- ) 00As mode %0000000000010000 or to mode ;
: 10As ( -- ) 00As mode %0000000000100000 or to mode ;
: 11As ( -- ) mode %0000000000110000 or to mode ;
: 0Ad ( -- ) mode %1111111101111111 and to mode ;
: 1Ad ( -- ) mode %0000000010000000 or to mode ;
\ -- Seven addressing modes for the source operand.
\ %0 = register mode Rn - As and Ad bits.
: sRn ( rn -- ) >sreg reset-src 00As ;
: Rn ( rn -- ) >dreg reset-src 00As ;
\ %1 = indexed mode X(Rn) - As and Ad bits.
\ (Rn + X) points to the operand.
\ X is stored in the next word.
: sX(Rn) ( x rn -- ) >sreg to src set-src 01As ;
: X(Rn) ( x rn -- ) >dreg to src set-src 01As ;
\ %1 Symbolic mode ADDR - As and Ad bits.
\ (PC + X) points to the operand.
\ X is stored in the next word. ( x == offset 16bit two-complement)
\ Indexed mode X(PC) is used.
: sADDR ( adr -- ) ( PC) 0 >sreg src-adr-offset to src set-src 01As ;
: ADDR ( adr -- ) ( PC) 0 >dreg src-adr-offset to src set-src 01As ;
\ %1 Absolute mode &ADDR - As and Ad bits.
\ The word following the instruction contains the absolute address.
\ Indexed mode X(SR) is used.
: s&ADDR ( adr -- ) ( SR) 2 >sreg to src set-src 01As ;
: &ADDR ( adr -- ) ( SR) 2 >dreg to src set-src 01As ;
\ %10 Indirect register mode @Rn - As bits only.
\ Rn is used as a pointer to the operand.
: s@Rn ( rn -- ) >sreg reset-src 10As ;
: @Rn ( rn -- ) >dreg reset-src 10As ;
\ %11 Indirect register autoincrement @Rn+ - As bits only.
\ Rn is used as a pointer to the operand.
\ Rn is incremented afterwards by 1 for .B instructions
\ and by 2 for .W instructions.
: s@Rn+ ( rn -- ) >sreg reset-src 11As ;
: @Rn+ ( rn -- ) >dreg reset-src 11As ;
\ %11 = Immediate mode #K - As bits only. See constant generator too
\ (It is called #K instead of #N because #N is used in syntax layer later on.)
\ The word following the instruction contains the immediate constant N.
\ Indirect autoincrement mode @PC+ is used.
: s#K ( k -- ) ( PC) 0 >sreg to src set-src 11As ;
: #K ( k -- ) ( PC) 0 >dreg to src set-src 11As ;
0 [if] \ Constant Generator Comment
One word less is compiled if CG1 or CG2 can be used as constant.
Table:
CG1 As
R2 00 Ð Ð Ð Ð Ð Register mode
R2 01 (0) Absolute address mode
R2 10 00004h +4, bit processing
R2 11 00008h +8, bit processing
CG2 As
R3 00 00000h 0, word processing
R3 01 00001h +1
R3 10 00002h +2, bit processing
R3 11 0FFFFh 1, word processing
To take advantage of constant gererators CG1 or CG2 use constant words.
e.g.: 2# 5 dRn mov, ( instead of 2 s#N 5 dRn mov, )
[then]
: 0# ( -- ) 3 >sreg reset-src 00As ;
: 1# ( -- ) 3 >sreg reset-src 01As ;
: 2# ( -- ) 3 >sreg reset-src 10As ;
: 4# ( -- ) 2 >sreg reset-src 10As ;
: 8# ( -- ) 2 >sreg reset-src 11As ;
: ffff# ( -- ) 3 >sreg reset-src 11As ;
\ -- Four addressing modes for the destination operand
\ %0 = register mode Rn - As and Ad bits.
: dRn ( rn -- ) >dreg reset-dst 0Ad ;
\ %1 = indexed mode X(Rn) - As and Ad bits.
\ (Rn + X) points to the operand.
\ X is stored in the next word.
: dX(Rn) ( x rn -- ) >dreg to dst set-dst 1Ad ;
\ %1 Symbolic mode ADDR - As and Ad bits.
\ (PC + X) points to the operand.
\ X is stored in the next word.
\ Indexed mode X(PC) is used.
: dADDR ( adr -- ) ( PC) 0 >dreg dst-adr-offset to dst set-dst 1Ad ;
\ %1 Absolute mode &ADDR - As and Ad bits.
\ The word following the instruction contains the absolute address.
\ Indexed mode X(SR) is used.
: d&ADDR ( adr -- ) ( SR) 2 >dreg to dst set-dst 1Ad ;
\ *** Table 3-17. MSP430 Instruction Set
\ Core instructions come first.
\ Emulatet instructions follow below.
\ Alphabetic order.
: (1) ; immediate \ comment: is emulated instruction.
: (2) ; immediate \ comment: is emulated instruction.
\ statusbits: [ V N Z C ]
\ * The status bit is affected
\ Ð The status bit is not affected
\ 0 The status bit is cleared
\ 1 The status bit is set
: .W ( op -- op.W ) %1111111110111111 and ;
: .B ( op -- op.B ) %0000000001000000 or ;
\ Core Instruction Set
\ Double-Operand (Format I) Instructions
\ bits: | 15 14 13 12 | 11 10 9 8 | 7 | 6 | 5 4 | 3 2 1 0 |
\ | Op-code | S-Reg | Ad | B/W | As | D-Reg |
: %16u.r $FFFF and &16 base @ >r 2 base ! u.r r> base ! ;
: checkI ( opcode -- )
cr ." formatI is: "
cr ." CCCC=Op-Code, SSSS=S-reg, d=Ad w=B/W, ss=As, RRRR=D/S-Reg."
cr ." FEDCBA9876543210"
cr ." CCCCSSSSdwssRRRR"
cr dup %16u.r space hex.
cr ;
\ Double-Operand syntax
\ Assembler example: ADD #10,R5
\ Forth: 10 s#N r5 dRn RRC,
\ src 10 is immediate mode, dst R5 is Register mode
: formatI ( op -- ) mode or op, src, dst, ;
: mneI: ( opcode "name" -- ) create , does> ( adr -- op ) @ formatI ;
$4000 .W mneI: MOV.W,
$5000 .W mneI: ADD.W,
$6000 .W mneI: ADDC.W,
$7000 .W mneI: SUBC.W,
$8000 .W mneI: SUB.W,
$9000 .W mneI: CMP.W,
$A000 .W mneI: DADD.W,
$B000 .W mneI: BIT.W,
$C000 .W mneI: BIC.W,
$D000 .W mneI: BIS.W,
$E000 .W mneI: XOR.W,
$F000 .W mneI: AND.W,
$4000 .B mneI: MOV.B,
$5000 .B mneI: ADD.B,
$6000 .B mneI: ADDC.B,
$7000 .B mneI: SUBC.B,
$8000 .B mneI: SUB.B,
$9000 .B mneI: CMP.B,
$A000 .B mneI: DADD.B,
$B000 .B mneI: BIT.B,
$C000 .B mneI: BIC.B,
$D000 .B mneI: BIS.B,
$E000 .B mneI: XOR.B,
$F000 .B mneI: AND.B,
' MOV.W, alias MOV,
' ADD.W, alias ADD,
' ADDC.W, alias ADDC,
' sUBC.W, alias SUBC,
' SUB.W, alias SUB,
' CMP.W, alias CMP,
' DADD.W, alias DADD,
' BIT.W, alias BIT,
' BIC.W, alias BIC,
' BIS.W, alias BIS,
' XOR.W, alias XOR,
' AND.W, alias AND,
\ Single-Operand (Format II) Instructions
\ BIts: | 15 14 13 12 11 10 9 8 7 | 6 | 5 4 | 3 2 1 0
\ | Op-code B/W As D/S-Reg
: checkII ( opcode -- )
cr ." formatII is:"
cr ." CCCCCCCCC=Op-Code, w=B/W, ss=As, RRRR=D/S-Reg."
cr ." FEDCBA9876543210"
cr ." CCCCCCCCCwssRRRR"
cr dup %16u.r space hex.
cr ;
\ Single-Operand syntax
\ Assembler example: RRC R5 ; Register mode
\ Forth: r5 rn RRC, \ r5 is a constant ( Rn may NOT be absent).
: formatII ( op -- ) mode or op, src, ;
: mneII: ( opcode "name" -- ) create , does> ( adr -- op ) @ formatII ;
$1000 .W mneII: RRC.W, ( src -- ) \ Rotate right through C [ * * * * ]
$1080 .W mneII: SWPB, ( src -- ) \ Swap bytes [ - - - - ]
$1100 .W mneII: RRA.W, ( src -- ) \ Rotate right arithmetically [ 0 * * * ]
$1180 .W mneII: SXT, ( src -- ) \ Extend sign [ 0 * * * ]
$1200 .W mneII: PUSH.W, ( src -- ) \ Push source onto stack: SP - 2 --> SP, src --> @SP [ - - - - ]
$1280 .W mneII: CALL, ( src -- ) \ Call destination: PC+2 --> stack, dst --> PC [ - - - - ]
$1040 .B mneII: RRC.B, ( src -- ) \ Rotate right through C [ * * * * ]
$1140 .B mneII: RRA.B, ( src -- ) \ Rotate right arithmetically [ 0 * * * ]
$1240 .B mneII: PUSH.B, ( src -- ) \ Push source onto stack: SP - 2 --> SP, src --> @SP [ - - - - ]
' RRC.W, alias RRC,
' RRA.W, alias RRA,
' PUSH.W, alias PUSH,
\ RETI is listed as a formatII instruction in User Guide,
\ but does not take any item from stack. So dont use mneII to create it.
: RETI, ( -- ) $1300 op, ; \ Return from subroutine: @SP --> PC, SP + 2 --> SP [ - - - - ]
\ Jump (Format-III) Instructions
\ Conditional-jump instruction format:
\ Bits: | 15 14 13 | 12 11 10 | 9 8 7 6 5 4 3 2 1 0 |
\ | Op-code | C | 10-Bit PC Offset |
: checkIII ( opcode -- )
cr ." formatIII is:"
cr ." CCCCCC=Op-Code, ooooooooo=offset."
cr ." FEDCBA9876543210"
cr ." CCCCCCoooooooooo"
cr dup %16u.r space hex.
cr ;
\ offset = number of words, i.e. bytes * 2 (10bit 2-complement).
\ Jump syntax
\ Assembler example: JMP label
\ Forth: label JMP,
: s>10 ( n -- n10 ) \ convert single precission to 10bit 2-complement.
dup %1111111111 and swap 0< if %1000000000 or then ;
: offsetIIIforward ( adr -- ) there swap - 2/ 1- s>10 ;
: offsetIIIback ( adr -- 10bit-pc-offset ) there - 2/ 1- s>10 ;
: formatIII ( adr op -- ) mode or swap offsetIIIback or op, ;
: mneIII: ( opcode "name" -- ) create , does> ( adr -- op ) @ formatIII ;
$2000 mneIII: JNE, ( adr -- ) \ Jump if not equal/Jump if Z not set [ - - - - ]
$2400 mneIII: JEQ, ( adr -- ) \ Jump if equal/Jump if Z set [ - - - - ]
$2800 mneIII: JNC, ( adr -- ) \ Jump if C not set/Jump if lower [ - - - - ]
$2C00 mneIII: JC, ( adr -- ) \ Jump if C set/Jump if higher or same [ - - - - ]
$3000 mneIII: JN, ( adr -- ) \ Jump if N set [ - - - - ]
$3400 mneIII: JGE, ( adr -- ) \ Jump if greater or equal[ - - - - ]
$3800 mneIII: JL, ( adr -- ) \ Jump if less[ - - - - ]
$3C00 mneIII: JMP, ( adr -- ) \ Jump PC + 2 * offset --> PC [ - - - - ]
' JNE, alias JNZ,
' JEQ, alias JZ,
' JNC, alias JLO,
' JC, alias JHS,
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\ -- label tabel
&10 constant maxlabels
variable (lbl) maxlabels cells allot
: >label ( n -- ) there swap cell * (lbl) + ! ;
: label> ( n -- addr ) cell * (lbl) + @ ;
: L0: 0 >label ;
: L1: 1 >label ;
: L2: 2 >label ;
: L3: 3 >label ;
: L4: 4 >label ;
: L5: 5 >label ;
: L6: 6 >label ;
: L7: 7 >label ;
: L8: 8 >label ;
: L9: 9 >label ;
: L0 0 label> ;
: L1 1 label> ;
: L2 2 label> ;
: L3 3 label> ;
: L4 4 label> ;
: L5 5 label> ;
: L6 6 label> ;
: L7 7 label> ;
: L8 8 label> ;
: L9 9 label> ;
: solve-forward ( adr -- ) >r r@ offsetIIIforward r@ X_@ or r> X_! ;
' solve-forward alias >>>
\ forward jump: L0: 000 Jxx ... L0 >>> ...
\ backward jump: L0: ... L0 Jxx ...
: .labels ( -- ) ." labels" cr maxlabels 0 do i . i label> . cr loop ;
: clrlabels ( -- ) maxlabels 0 do i >label loop ;
true [if] ( verification process )
variable nops variable errnops
: (.lst) ( adr n -- adr n ) \ list last compiled instruction.
cr source type 3 spaces loca hex.
there loca - 0 ?do loca i + X_@ X_. 2 +loop ;
: .lst ( adr n -- ) 2drop (.lst) .s ;
: $op ( adr n -- ) drop &14 + 4 evaluate 1 nops +! ;
: X_w@be { adr -- w } adr X_c@ 8 lshift adr 1+ X_c@ + ; \ big endian.
: ops? ( adr n -- ) $op loca X_w@be = ;
: .chk ( adr n -- ) \ check last compiled instruktion.
(.lst) ops? if .s ." Vop " else .s ." <--- Nop " 1 errnops +! then ;
0 value startadr 0 value endadr
: .startcode ( -- )
there to startadr ." there=" there hex. cr
[op] reset-src reset-dst 0 to mode ;
: .endcode ( -- )
there to endadr ." there=" there hex. cr ;
: .dumpcode ( -- )
cr ." dump code area" startadr tstart + endadr startadr - dump ;
: .dumpcode-all ( -- )
cr ." dump code area" tstart endadr dump ;
: verification ( -- ) cr .startcode clrlabels 0 nops ! ;
: .result ( -- )
cr nops @ . ." opcodes & addressing modes tested."
cr errnops @ . ." non matching opcodes." ;
[then]
include syntaxlayer.fs ( secondary syntax layer to ease coding)
include emuset.fs
HERE SWAP - .( \ Length of MSP430-Assembler: ) . .( Bytes ) CR
hex
\ .( -- words so far: ) words cr .( -- end of wordlist) cr cr
\ finis