Added names to byte cells, for debugging purposes.
[sixpic.git] / pic18-sim.scm
blob0fbdcda26dcda06028a4f303d261434c5453b314
1 ;;; File: "pic18-sim.scm"
3 (define pic18-ram   #f)
4 (define pic18-rom   #f)
5 (define pic18-stack #f)
6 (define pic18-pc    #f)
7 (define pic18-wreg  #f)
9 (define instrs-counts #f) ; counts how many times each instruction is executed
10 (define break-points '()) ; list of adresses at which the simulation stops
12 (define pic18-carry-flag    #f)
13 (define pic18-deccarry-flag #f)
14 (define pic18-zero-flag     #f)
15 (define pic18-overflow-flag #f)
16 (define pic18-negative-flag #f)
18 (define pic18-cycles #f)
19 (define pic18-exit #f)
21 (define (get-ram adr)
22   (cond ((= adr TOSU)
23          (bitwise-and (arithmetic-shift (get-tos) -16) #xff))
24         ((= adr TOSH)
25          (bitwise-and (arithmetic-shift (get-tos) -8) #xff))
26         ((= adr TOSL)
27          (bitwise-and (get-tos) #xff))
28         ((= adr PCL)
29          (set-ram PCLATU (bitwise-and (arithmetic-shift (get-pc) -16) #x1f))
30          (set-ram PCLATH (bitwise-and (arithmetic-shift (get-pc) -8)  #xff))
31          (bitwise-and (get-pc) #xfe))
32         ((= adr STATUS)
33          (+ pic18-carry-flag
34             (arithmetic-shift pic18-deccarry-flag 1)
35             (arithmetic-shift pic18-zero-flag 2)
36             (arithmetic-shift pic18-overflow-flag 3)
37             (arithmetic-shift pic18-negative-flag 4)))
38         ((assq adr (list (cons INDF0 (cons FSR0H FSR0L))
39                          (cons INDF1 (cons FSR1H FSR1L))
40                          (cons INDF2 (cons FSR2H FSR2L))))
41          => (lambda (x)
42               (get-ram (bitwise-ior
43                         (arithmetic-shift (bitwise-and (u8vector-ref pic18-ram
44                                                                      (cadr x))
45                                                        #xf)
46                                           8)
47                         (u8vector-ref pic18-ram
48                                       (cddr x))))))
49         ;; TODO pre/post inc/dec 0..2
50         (else
51          (u8vector-ref pic18-ram adr))))
53 (define (set-ram adr byte)
54   (cond ((= adr TOSU)
55          (set-tos (+ (bitwise-and (get-tos) #x00ffff)
56                      (arithmetic-shift (bitwise-and byte #x1f) 16))))
57         ((= adr TOSH)
58          (set-tos (+ (bitwise-and (get-tos) #x1f00ff)
59                      (arithmetic-shift byte 8))))
60         ((= adr TOSL)
61          (set-tos (+ (bitwise-and (get-tos) #x1fff00)
62                      byte)))
63         ((= adr PCL)
64          (set-pc (+ (bitwise-and (arithmetic-shift (get-ram PCLATU) 16) #x1f)
65                     (bitwise-and (arithmetic-shift (get-ram PCLATH) 8) #xff)
66                     (bitwise-and byte #xfe))))
67         ((= adr STATUS)
68          (set! pic18-carry-flag    (bitwise-and byte 1))
69          (set! pic18-deccarry-flag (arithmetic-shift (bitwise-and byte 2) -1))
70          (set! pic18-zero-flag     (arithmetic-shift (bitwise-and byte 4) -2))
71          (set! pic18-overflow-flag (arithmetic-shift (bitwise-and byte 8) -3))
72          (set! pic18-negative-flag (arithmetic-shift (bitwise-and byte 16) -4)))
73         ((assq adr (list (cons INDF0 (cons FSR0H FSR0L))
74                          (cons INDF1 (cons FSR1H FSR1L))
75                          (cons INDF2 (cons FSR2H FSR2L))))
76          => (lambda (x)
77               (set-ram (bitwise-ior ;; TODO factor common code with get-ram ?
78                         (arithmetic-shift (bitwise-and (u8vector-ref pic18-ram
79                                                                      (cadr x))
80                                                        #xf)
81                                           8)
82                         (u8vector-ref pic18-ram
83                                       (cddr x)))
84                        byte)))
85         ;; TODO all other special array registers
86         (else
87          (u8vector-set! pic18-ram adr byte))))
89 (define (get-rom adr)
90   (u8vector-ref pic18-rom adr))
92 (define (set-rom adr byte)
93   (u8vector-set! pic18-rom adr byte))
95 (define (get-stack adr)
96   (vector-ref pic18-stack adr))
98 (define (set-stack adr pc)
99   (vector-set! pic18-stack adr pc))
101 (define (get-pc)
102   pic18-pc)
104 (define (set-pc pc)
105   (set! pic18-pc pc))
107 (define (get-sp)
108   (bitwise-and (get-ram STKPTR) #x1f))
110 (define (set-sp sp)
111   (set-ram STKPTR
112            (bitwise-ior sp
113                         (bitwise-and (get-ram STKPTR) #xe0))))
115 (define (get-tos)
116   (vector-ref pic18-stack (- (get-sp) 1)))
118 (define (set-tos pc)
119   (vector-set! pic18-stack (- (get-sp) 1) pc))
121 (define (stack-push pc)
122   (set-sp (+ (get-sp) 1))
123   (set-tos pc))
125 (define (stack-pop)
126   (set-pc (get-tos))
127   (set-sp (- (get-sp) 1)))
129 (define (get-bsr)
130   (bitwise-and (get-ram BSR) #x0f))
132 (define (get-wreg)
133   pic18-wreg)
135 (define (set-wreg byte)
136   (set! pic18-wreg byte))
138 (define (zero-flag?)
139   (not (= 0 pic18-zero-flag)))
141 (define (set-zero-flag flag)
142   (set! pic18-zero-flag flag))
144 (define (negative-flag?)
145   (not (= 0 pic18-negative-flag)))
147 (define (set-negative-flag flag)
148   (set! pic18-negative-flag flag))
150 (define (carry-flag?)
151   (not (= 0 pic18-carry-flag)))
153 (define (set-carry-flag flag)
154   (set! pic18-carry-flag flag))
156 (define (deccarry-flag?)
157   (not (= 0 pic18-deccarry-flag)))
159 (define (set-deccarry-flag flag)
160   (set! pic18-deccarry-flag flag))
162 (define (overflow-flag?)
163   (not (= 0 pic18-overflow-flag)))
165 (define (set-overflow-flag flag)
166   (set! pic18-overflow-flag flag))
168 (define (pic18-sim-setup)
169   (set! pic18-ram     (make-u8vector #x1000  0))
170   (set! pic18-rom     (make-u8vector #x10000 0))
171   (set! pic18-stack   (make-vector   #x1f    0))
172   (set! instrs-counts (make-vector   #x10000 0))
173   (set-pc 0)
174   (set-wreg 0)
175   (set! pic18-carry-flag    0)
176   (set! pic18-deccarry-flag 0)
177   (set! pic18-zero-flag     0)
178   (set! pic18-overflow-flag 0)
179   (set! pic18-negative-flag 0))
181 (define (pic18-sim-cleanup)
182   (set! pic18-ram   #f)
183   (set! pic18-rom   #f)
184   (set! pic18-stack #f))
186 ;------------------------------------------------------------------------------
188 (define (last-pc)
189   (let ((pc (- (get-pc) 2)))
190     (list (get-sp) " " (- pic18-cycles 1) " "
191           (substring (number->string (+ #x1000000 pc) 16) 1 7)
192           "     ")))
194 (define (illegal-opcode opcode)
195   (if trace-instr
196       (print (list (last-pc) "  *illegal*")))
197   (error "illegal opcode" opcode))
199 (define decode-vector
200   (make-vector 256 illegal-opcode))
202 (define (decode-opcode opcode-bits shift action)
203   (if (< shift 8)
204       (error "shift=" shift))
205   (let ((n (arithmetic-shift 1 (- shift 8)))
206         (base (arithmetic-shift opcode-bits (- shift 8))))
207     (let loop ((i 0))
208       (if (< i n)
209           (begin
210             (vector-set! decode-vector (+ base i) action)
211             (loop (+ i 1)))))))
213 (define (byte-oriented opcode mnemonic flags-changed operation)
214   (byte-oriented-aux opcode mnemonic flags-changed operation 'wreg))
215 (define (byte-oriented-file opcode mnemonic flags-changed operation)
216   (byte-oriented-aux opcode mnemonic flags-changed operation 'file))
217 (define (byte-oriented-wide opcode mnemonic flags-changed operation dest)
218   ;; for use with instructions that have results more than a byte wide, such
219   ;; as multiplication. the result goes at the given addresses
220   (byte-oriented-aux opcode mnemonic flags-changed operation dest)) ;; TODO do the same for literals
222 (define (byte-oriented-aux opcode mnemonic flags-changed operation dest)
223   (let* ((f (bitwise-and opcode #xff))
224          (adr (if (= 0 (bitwise-and opcode #x100))
225                   ;; the upper 160 addresses of the first bank are the special
226                   ;; registers #xF60 to #xFFF
227                   (if (= 0 (bitwise-and f #x80)) f (+ f #xf00))
228                   (+ f (arithmetic-shift (get-bsr) 8)))))
229     (if trace-instr
230         (print (list (last-pc) "        " mnemonic "    "
231                        (let ((x (assv adr file-reg-names)))
232                          (if x (cdr x) (list "0x" (number->string adr 16))))
233                        (if (or (eq? dest 'wreg)
234                                (= 0 (bitwise-and opcode #x200)))
235                            ", w"
236                            "")
237                        "")))
238     (let* ((result (operation (get-ram adr)))
239            (result-8bit (bitwise-and result #xff)))
240       (cond ((list? dest)
241              ;; result is more than a byte wide (i.e. multiplication)
242              ;; put it in the right destinations (dest is a list of addresses)
243              (let loop ((dest dest) (result result))
244                (if (not (null? dest))
245                    ;; the head of the list is the lsb
246                    (begin (set-ram (car dest) (bitwise-and result #xff))
247                           (loop (cdr dest) (arithmetic-shift result -8))))))
248             ((or (eq? dest 'file) (not (= 0 (bitwise-and opcode #x200))))
249              ;; the result goes in memory (file)
250              (set-ram adr result-8bit))
251             ((eq? dest 'wreg)
252              ;; result goes in wreg
253              (set-wreg result-8bit)))
254       (if (not (eq? flags-changed 'none))
255           (begin
256             (set-zero-flag (if (= 0 result-8bit) 1 0))
257             (if (not (eq? flags-changed 'z))
258                 (begin
259                   (set-negative-flag (if (> result-8bit #x7f) 1 0))
260                   (if (not (eq? flags-changed 'z-n))
261                       (begin
262                         (set-carry-flag (if (or (> result #xff)
263                                                 (< result 0))
264                                             1 0))
265                         (if (not (eq? flags-changed 'c-z-n))
266                             (begin
267                               (set-deccarry-flag 0);;;;;;;;;;;;;;
268                               (set-overflow-flag 0))))))))))));;;;;;;;;;;;;;
270 (define (bit-oriented opcode mnemonic operation)
271   (let* ((f (bitwise-and opcode #xff))
272          (adr (if (= 0 (bitwise-and opcode #x100))
273                   (if (= 0 (bitwise-and f #x80)) f (+ f #xf00))
274                   (+ f (arithmetic-shift (get-bsr) 8))))
275          (b (bitwise-and (arithmetic-shift opcode -9) 7)))
276     (if trace-instr
277         (print (list (last-pc) "        " mnemonic "    "
278                        (let ((x (assv adr file-reg-names)))
279                          (if x (cdr x) (list "0x" (number->string adr 16))))
280                        ", "
281                        (if (= adr STATUS)
282                            (cdr (assv b '((0 . C)
283                                           (1 . DC)
284                                           (2 . Z)
285                                           (3 . OV)
286                                           (4 . N)
287                                           (5 . 5)
288                                           (6 . 6)
289                                           (7 . 7))))
290                            b)
291                        "")))
292     (let* ((result (operation (get-ram adr) b))
293            (result-8bit (bitwise-and result #xff)))
294       (set-ram adr result-8bit))))
296 (define (short-relative-branch opcode mnemonic branch)
297   (let* ((n (bitwise-and opcode #xff))
298          (adr (+ (get-pc) (* 2 (if (> n #x7f) (- n #x100) n)))))
299     (if trace-instr
300         (print (list (last-pc) "        " mnemonic "    "
301                      (symbol->string (table-ref symbol-table adr)))))
302     (if (branch)
303         (begin
304           (get-program-mem)
305           (set-pc adr)))))
307 (define (long-relative-branch opcode mnemonic call?)
308   (let* ((n (bitwise-and opcode #x7ff))
309          (adr (+ (get-pc) (* 2 (if (> n #x3ff) (- n #x800) n)))))
310     (if trace-instr
311         (print (list (last-pc) "        " mnemonic "    "
312                      (symbol->string (table-ref symbol-table adr)))))
313     (if call?
314         (stack-push (get-pc)))
315     (get-program-mem)
316     (set-pc adr)))
318 (define (call-branch opcode mnemonic)
319   (let ((adr (* 2 (+ (bitwise-and opcode #xff)
320                      (arithmetic-shift (bitwise-and (get-program-mem) #xfff) 8)))))
321     (if trace-instr
322         (print (list (last-pc) "        " mnemonic "    "
323                      (symbol->string (table-ref symbol-table adr))
324                      (if (= 0 (bitwise-and opcode #x100))
325                          ""
326                          ", FAST"))))
327     (stack-push (get-pc))
328     (if (not (= 0 (bitwise-and opcode #x100)))
329         (error "call fast not implemented"))
330     (set-pc adr)))
332 (define (goto-branch opcode mnemonic)
333   (let ((adr (* 2 (+ (bitwise-and opcode #xff)
334                      (arithmetic-shift (bitwise-and (get-program-mem) #xfff) 8)))))
335     (if trace-instr
336         (print (list (last-pc) "        " mnemonic "    "
337                      (symbol->string (table-ref symbol-table adr)))))
338     (set-pc adr)))
340 (define (literal-operation opcode mnemonic flags-changed operation)
341   (let ((k (bitwise-and opcode #xff)))
342     (if trace-instr
343         (print (list (last-pc) "        " mnemonic "    "
344                        (if (< k 10) k (list "0x" (number->string k 16))))))
345     (let* ((result (operation k))
346            (result-8bit (bitwise-and result #xff)))
347       (set-wreg result-8bit)
348       (if (not (eq? flags-changed 'none))
349           (begin
350             (set-zero-flag (if (= 0 result-8bit) 1 0))
351             (if (not (eq? flags-changed 'z))
352                 (begin
353                   (set-negative-flag (if (> result-8bit #x7f) 1 0))
354                   (if (not (eq? flags-changed 'z-n))
355                       (begin
356                         (set-carry-flag (if (> result #xff) 1 0))
357                         (if (not (eq? flags-changed 'c-z-n))
358                             (begin
359                               (set-deccarry-flag 0);;;;;;;;;;;;;;
360                               (set-overflow-flag 0))))))))))));;;;;;;;;;;;;;
362 (define (program-memory-read mnemonic read-adr-fun set-adr-fun)
363   (if trace-instr
364       (print (list (last-pc) "  " mnemonic "    ")))
365   (let ((adr (bitwise-ior (arithmetic-shift (get-ram TBLPTRU) 16)
366                           (arithmetic-shift (get-ram TBLPTRH) 8)
367                           (get-ram TBLPTRL))))
368     (set-ram TABLAT (get-rom (bitwise-and (read-adr-fun adr)
369                                           ;; rom addresses are 21 bits wide
370                                           #x1fffff)))
371     (let ((new-adr (bitwise-and (set-adr-fun adr) #x1fffff)))
372       (set-ram TBLPTRU (arithmetic-shift new-adr -16))
373       (set-ram TBLPTRH (bitwise-and (arithmetic-shift new-adr -8) #xff))
374       (set-ram TBLPTRL (bitwise-and new-adr #xff)))))
376 (define (get-program-mem)
377   (set! pic18-cycles (+ pic18-cycles 1))
378   (let* ((pc (get-pc))
379          (lsb (get-rom pc))
380          (msb (get-rom (+ pc 1))))
381     (set-pc (+ (get-pc) 2))
382     (+ (arithmetic-shift msb 8) lsb)))
384 (define (skip)
385   (get-program-mem))
387 (define (hex n)
388   (substring (number->string (+ #x100 n) 16) 1 3))
390 (define (dump-mem)
392   (print "      ")
393   (let loop ((i 0))
394     (if (< i 10)
395         (begin
396           (print (list (hex (u8vector-ref pic18-ram i)) " "))
397           (loop (+ i 1)))))
398   (print (list "  WREG=" (hex (get-wreg)) "\n")))
400 (define single-stepping-mode? #f)
401 (define (pic18-execute)
402   (set! pic18-exit #f)
403   (set! pic18-cycles 0)
404   (if trace-instr
405       (print "                          "))
406   (let loop ()
407     (if trace-instr
408         (dump-mem))
409     (if pic18-exit
410         (begin
411           (print (list "WREG = d'" (get-wreg) "'\n")))
412         (let ((opcode (get-program-mem))
413               (pc     (- (get-pc) 2)))
414           (vector-set! instrs-counts pc (+ (vector-ref instrs-counts pc) 1))
415           (if (member pc break-points)
416               (begin (pp (list "break point at: " (number->string pc 16)))
417                      (set! trace-instr #t)
418                      (set! single-stepping-mode? #t)))
419           (if single-stepping-mode? (step))
420           (let ((proc (vector-ref decode-vector (arithmetic-shift opcode -8))))
421             (proc opcode)
422             (loop))))))
424 (define trace-instr #t)
426 (define (carry)
427   (if (> pic18-carry-flag 0)
428       (begin (set! pic18-carry-flag #f)
429              1)
430       0))
432 ;------------------------------------------------------------------------------
434 ; Byte-oriented file register operations.
436 (decode-opcode #b001001 10
437   (lambda (opcode)
438     (byte-oriented opcode "addwf" 'c-dc-z-ov-n
439      (lambda (f)
440        (+ f (get-wreg))))))
442 (decode-opcode #b001000 10
443   (lambda (opcode)
444     (byte-oriented opcode "addwfc" 'c-dc-z-ov-n
445      (lambda (f)
446        (+ f (get-wreg) (carry))))))
448 (decode-opcode #b000101 10
449   (lambda (opcode)
450     (byte-oriented opcode "andwf" 'z-n
451      (lambda (f)
452        (bitwise-and f (get-wreg))))))
454 (decode-opcode #b0110101 9
455   (lambda (opcode)
456     (byte-oriented-file opcode "clrf" 'z
457      (lambda (f)
458        0))))
460 (decode-opcode #b000111 10
461   (lambda (opcode)
462     (byte-oriented opcode "comf" 'z-n
463      (lambda (f)
464        (bitwise-not f)))))
466 (decode-opcode #b0110001 9
467   (lambda (opcode)
468     (byte-oriented-file opcode "cpfseq" 'none
469      (lambda (f)
470        (if (= f (get-wreg)) (skip))
471        f))))
473 (decode-opcode #b0110010 9
474   (lambda (opcode)
475     (byte-oriented-file opcode "cpfsgt" 'none
476      (lambda (f)
477        (if (> f (get-wreg)) (skip))
478        f))))
480 (decode-opcode #b0110000 9
481   (lambda (opcode)
482     (byte-oriented-file opcode "cpfslt" 'none
483      (lambda (f)
484        (if (< f (get-wreg)) (skip))
485        f))))
487 (decode-opcode #b000001 10
488   (lambda (opcode)
489     (byte-oriented opcode "decf" 'c-dc-z-ov-n
490      (lambda (f)
491        (- f 1)))))
493 (decode-opcode #b001011 10
494   (lambda (opcode)
495     (byte-oriented opcode "decfsz" 'none
496      (lambda (f)
497        (if (= f 1) (skip))
498        (- f 1)))))
500 (decode-opcode #b010011 10
501   (lambda (opcode)
502     (byte-oriented opcode "dcfsnz" 'none
503      (lambda (f)
504        (if (not (= f 1)) (skip))
505        (- f 1)))))
507 (decode-opcode #b001010 10
508   (lambda (opcode)
509     (byte-oriented opcode "incf" 'c-dc-z-ov-n
510      (lambda (f)
511        (+ f 1)))))
513 (decode-opcode #b001111 10
514   (lambda (opcode)
515     (byte-oriented opcode "incfsz" 'none
516      (lambda (f)
517        (if (= f #xff) (skip))
518        (+ f 1)))))
520 (decode-opcode #b010010 10
521   (lambda (opcode)
522     (byte-oriented opcode "infsnz" 'none
523      (lambda (f)
524        (if (not (= f #xff)) (skip))
525        (+ f 1)))))
527 (decode-opcode #b000100 10
528   (lambda (opcode)
529     (byte-oriented opcode "iorwf" 'z-n
530      (lambda (f)
531        (bitwise-ior f (get-wreg))))))
533 (decode-opcode #b010100 10
534   (lambda (opcode)
535     (byte-oriented opcode "movf" 'z-n
536      (lambda (f)
537        f))))
539 (decode-opcode #b1100 12
540   (lambda (opcode)
541     (let* ((src (bitwise-and opcode #xfff))
542            ;; the destination is in the second 16-bit part, need to fetch
543            (dst (bitwise-and (get-program-mem) #xfff)))
544       (if trace-instr
545           (print (list (last-pc) "      movff   "
546                        (let ((x (assv src file-reg-names)))
547                          (if x (cdr x) (list "0x" (number->string src 16))))
548                        ", "
549                        (let ((x (assv dst file-reg-names)))
550                          (if x (cdr x) (list "0x" (number->string dst 16)))) ;; TODO printing 2 args ruins the formatting
551                        "")))
552       (set-ram dst (get-ram src)))))
554 (decode-opcode #b0110111 9
555   (lambda (opcode)
556     (byte-oriented-file opcode "movwf" 'none
557      (lambda (f)
558        (get-wreg)))))
560 (decode-opcode #b0000001 9
561   (lambda (opcode)
562     (byte-oriented-wide opcode "mulwf" 'none
563      (lambda (f)
564        (* f (get-wreg)))
565      (list PRODL PRODH))))
567 (decode-opcode #b0110110 9
568   (lambda (opcode)
569     (byte-oriented-file opcode "negf" 'c-dc-z-ov-n
570      (lambda (f)
571        (- f)))))
573 (decode-opcode #b001101 10
574   (lambda (opcode)
575     (byte-oriented opcode "rlcf" 'c-z-n
576      (lambda (f)
577        ;; the carry flag will be set automatically
578        (+ (arithmetic-shift f 1) (carry))))))
580 (decode-opcode #b010001 10
581   (lambda (opcode)
582     (byte-oriented opcode "rlncf" 'z-n
583      (lambda (f)
584        (+ (arithmetic-shift f 1) (arithmetic-shift f -7))))))
586 (decode-opcode #b001100 10
587   (lambda (opcode)
588     (byte-oriented opcode "rrcf" 'c-z-n
589      (lambda (f)
590        (let ((r (+ (arithmetic-shift f -1) (arithmetic-shift (carry) 7))))
591          ;; roll through carry (if the result is over #xff, carry will be set)
592          (if (= (bitwise-and f 1) 1) (+ r #x100) r))))))
594 (decode-opcode #b010000 10
595   (lambda (opcode)
596     (byte-oriented opcode "rrncf" 'z-n
597      (lambda (f)
598        (+ (arithmetic-shift f -1) (arithmetic-shift f 7))))))
600 (decode-opcode #b0110100 9
601   (lambda (opcode)
602     (byte-oriented-file opcode "setf" 'z
603      (lambda (f)
604        #xff))))
606 (decode-opcode #b010101 10
607   (lambda (opcode)
608     (byte-oriented opcode "subfwb" 'c-dc-z-ov-n
609      (lambda (f)
610        (- (get-wreg) f (carry))))))
612 (decode-opcode #b010111 10
613   (lambda (opcode)
614     (byte-oriented opcode "subwf" 'c-dc-z-ov-n
615      (lambda (f)
616        (- f (get-wreg))))))
618 (decode-opcode #b010110 10
619   (lambda (opcode)
620     (byte-oriented opcode "subwfb" 'c-dc-z-ov-n
621      (lambda (f)
622        (- f (get-wreg) (carry))))))
624 (decode-opcode #b001110 10
625   (lambda (opcode)
626     (byte-oriented opcode "swapf" 'none
627      (lambda (f)
628        (+ (arithmetic-shift f -4) (arithmetic-shift f 4))))))
630 (decode-opcode #b0110011 9
631   (lambda (opcode)
632     (byte-oriented-file opcode "tstfsz" 'none
633      (lambda (f)
634        (if (= f 0) (skip))))))
636 (decode-opcode #b000110 10
637   (lambda (opcode)
638     (byte-oriented opcode "xorwf" 'z-n
639      (lambda (f)
640        (bitwise-xor f (get-wreg))))))
642 ; Bit-oriented file register operations.
644 (decode-opcode #b1001 12
645   (lambda (opcode)
646     (bit-oriented opcode "bcf"
647      (lambda (f b)
648        (bitwise-and f (bitwise-not (arithmetic-shift 1 b)))))))
650 (decode-opcode #b1000 12
651   (lambda (opcode)
652     (bit-oriented opcode "bsf"
653      (lambda (f b)
654        (bitwise-ior f (arithmetic-shift 1 b))))))
656 (decode-opcode #b1011 12
657   (lambda (opcode)
658     (bit-oriented opcode "btfsc"
659      (lambda (f b)
660        (if (= 0 (bitwise-and f (arithmetic-shift 1 b))) (skip))
661        f))))
663 (decode-opcode #b1010 12
664   (lambda (opcode)
665     (bit-oriented opcode "btfss"
666      (lambda (f b)
667        (if (not (= 0 (bitwise-and f (arithmetic-shift 1 b)))) (skip))
668        f))))
670 (decode-opcode #b0111 12
671   (lambda (opcode)
672     (bit-oriented opcode "btg"
673      (lambda (f b)
674        (bitwise-xor f (arithmetic-shift 1 b))))))
676 ; Control operations.
678 (decode-opcode #b11100010 8
679   (lambda (opcode)
680     (short-relative-branch opcode "bc"
681      (lambda ()
682        (not (= 0 (carry)))))))
684 (decode-opcode #b11100110 8
685   (lambda (opcode)
686     (short-relative-branch opcode "bn" negative-flag?)))
688 (decode-opcode #b11100011 8
689   (lambda (opcode)
690     (short-relative-branch opcode "bnc"
691      (lambda ()
692        (= 0 (carry))))))
694 (decode-opcode #b11100111 8
695   (lambda (opcode)
696     (short-relative-branch opcode "bnn" negative-flag?)))
698 (decode-opcode #b11100101 8
699   (lambda (opcode)
700     (short-relative-branch opcode "bnov"
701      (lambda ()
702        (not (overflow-flag?))))))
704 (decode-opcode #b11100001 8
705   (lambda (opcode)
706     (short-relative-branch opcode "bnz"
707      (lambda ()
708        (not (zero-flag?))))))
710 (decode-opcode #b11100100 8
711   (lambda (opcode)
712     (short-relative-branch opcode "bov" overflow-flag?)))
714 (decode-opcode #b11010 11
715   (lambda (opcode)
716     (long-relative-branch opcode "bra" #f)))
718 (decode-opcode #b11100000 8
719   (lambda (opcode)
720     (short-relative-branch opcode "bz" zero-flag?)))
722 (decode-opcode #b1110110 9
723   (lambda (opcode)
724     (call-branch opcode "call")))
726 (decode-opcode #b11101111 8
727   (lambda (opcode)
728     (goto-branch opcode "goto")))
730 (decode-opcode #b11011 11
731   (lambda (opcode)
732     (long-relative-branch opcode "rcall" #t)))
734 (decode-opcode #b1111 12
735   (lambda (opcode)
736     (if trace-instr
737         (print (list (last-pc) "        nop     ")))))
739 (decode-opcode #b00000000 8
740   (lambda (opcode)
741     (cond ((= opcode #b0000000000000100)
742            (if trace-instr
743                (print (list (last-pc) " clrwdt  ")))
744            (clrwdt opcode))
745           ((= opcode #b0000000000000111)
746            (if trace-instr
747                (print (list (last-pc) " daw     ")))
748            (daw opcode))
749           ((= opcode #b0000000000000000)
750            (if trace-instr
751                (print (list (last-pc) " nop     "))))
752           ((= opcode #b0000000000000110)
753            (if trace-instr
754                (print (list (last-pc) " pop     ")))
755            (stack-pop))
756           ((= opcode #b0000000000000101)
757            (if trace-instr
758                (print (list (last-pc) " push    ")))
759            (stack-push (get-pc)))
760           ((= opcode #b0000000011111111)
761            (if trace-instr
762                (print (list (last-pc) " reset   ")))
763            (set-pc 0))
764           ((= opcode #b0000000000010000)
765            (if trace-instr
766                (print (list (last-pc) " retfie  ")))
767            (get-program-mem)
768            (stack-pop))
769           ((= opcode #b0000000000010001)
770            (if trace-instr
771                (print (list (last-pc) " retfie  FAST")))
772            (error "retfie fast not implemented")
773            (get-program-mem)
774            (stack-pop))
775           ((= opcode #b0000000000010010)
776            (if trace-instr
777                (print (list (last-pc) " return  ")))
778            (get-program-mem)
779            (stack-pop))
780           ((= opcode #b0000000000010011)
781            (if trace-instr
782                (print (list (last-pc) " return  FAST")))
783            (error "return fast not implemented")
784            (get-program-mem)
785            (stack-pop))
786           ((= opcode #b0000000000000011)
787            (if trace-instr
788                (print (list (last-pc) " sleep   ")))
789            (set! pic18-exit #t))
790           ;; program memory operations
791           ((= opcode #b0000000000001000)
792            (program-memory-read   "tblrd*"  identity identity))
793           ((= opcode #b0000000000001001)
794            (program-memory-read   "tblrd*+" identity (lambda (adr) (+ adr 1))))
795           ((= opcode #b0000000000001010)
796            (program-memory-read   "tblrd*-" identity (lambda (adr) (- adr 1))))
797           ((= opcode #b0000000000001011)
798            (program-memory-read   "tblrd+*"
799                                   (lambda (adr) (+ adr 1))
800                                   (lambda (adr) (+ adr 1))))
801           ((= opcode #b0000000000001100)
802            (program-memory-write  "tblwt*"  identity identity)) ;; TODO not implemented
803           ((= opcode #b0000000000001101)
804            (program-memory-write  "tblwt*+" identity (lambda (adr) (+ adr 1))))
805           ((= opcode #b0000000000001110)
806            (program-memory-write  "tblwt*-" identity (lambda (adr) (- adr 1))))
807           ((= opcode #b0000000000001111)
808            (program-memory-write  "tblwt+*"
809                                   (lambda (adr) (+ adr 1))
810                                   (lambda (adr) (+ adr 1))))
811           (else
812            (if trace-instr
813                (print (list (last-pc) " ???     ")))
814            (error "???")))))
816 ; Literal operations.
818 (decode-opcode #b00001111 8
819   (lambda (opcode)
820     (literal-operation opcode "addlw" 'c-dc-z-ov-n
821      (lambda (k)
822        (+ k (get-wreg))))))
824 (decode-opcode #b00001011 8
825   (lambda (opcode)
826     (literal-operation opcode "andlw" 'z-n
827      (lambda (k)
828        (bitwise-and k (get-wreg))))))
830 (decode-opcode #b00001001 8
831   (lambda (opcode)
832     (literal-operation opcode "iorlw" 'z-n
833      (lambda (k)
834        (bitwise-ior k (get-wreg))))))
837 (define (lfsr f k)
838   (make-instruction
839    2
840    (lambda ()
841      (make-listing "lfsr" (file-text f) (lit-text k)))
842    (lambda ()
843      (asm-16 (bitmask "1110 1110 00ff kkkk" (file f) (quotient (lit k) 256)))
844      (asm-16 (bitmask "1111 0000 kkkk kkkk" (modulo (lit k) 256))))))
847 (define (movlb k)
848   (make-instruction
849    1
850    (lambda ()
851      (make-listing "movlb" (lit-text k)))
852    (lambda ()
853      (asm-16 (bitmask "0000 0001 0000 kkkk" (lit k))))))
855 (decode-opcode #b00001110 8
856   (lambda (opcode)
857     (literal-operation opcode "movlw" 'none
858      (lambda (k)
859        k))))
861 (decode-opcode #b00001101 8
862   (lambda (opcode)
863     (literal-operation opcode "mullw" 'none
864      (lambda (k)
865        (* k (get-wreg))))))
867 (decode-opcode #b00001100 8
868   (lambda (opcode)
869     (literal-operation opcode "retlw" 'none
870      (lambda (k)
871        (get-program-mem)
872        (stack-pop)
873        k))))
875 (decode-opcode #b00001000 8
876   (lambda (opcode)
877     (literal-operation opcode "sublw" 'c-dc-z-ov-n
878      (lambda (k)
879        (- k (get-wreg))))))
881 (decode-opcode #b00001010 8
882   (lambda (opcode)
883     (literal-operation opcode "xorlw" 'z-n
884      (lambda (k)
885        (bitwise-xor k (get-wreg))))))
888 ;------------------------------------------------------------------------------
890 (define (read-hex-file filename)
892   (define addr-width 32)
894   (define (syntax-error)
895     (error "*** Syntax error in HEX file"))
897   (let ((f
898          (with-exception-catcher
899           (lambda (exc)
900             #f)
901           (lambda ()
902             (open-input-file filename)))))
904     (define mem (make-vector 16 #f))
906     (define (mem-store! a b)
907       (let loop ((m mem)
908                  (a a)
909                  (x (- addr-width 4)))
910         (if (= x 0)
911             (vector-set! m a b)
912             (let ((i (arithmetic-shift a (- x))))
913               (let ((v (vector-ref m i)))
914                 (loop (or v
915                           (let ((v (make-vector 16 #f)))
916                             (vector-set! m i v)
917                             v))
918                       (- a (arithmetic-shift i x))
919                       (- x 4)))))))
921     (define (mem->list)
923       (define (f m a n tail)
925         (define (g i a n tail)
926           (if (>= i 0)
927               (g (- i 1) (- a n) n (f (vector-ref m i) a n tail))
928               tail))
930         (if m
931             (if (= n 1)
932                 (cons (cons (- a 1) m) tail)
933                 (g 15 a (quotient n 16) tail))
934             tail))
936       (f mem (expt 2 addr-width) (expt 2 addr-width) '()))
938     (define hi16
939       0)
941     (define (read-hex-nibble)
942       (let ((c (read-char f)))
943         (cond ((and (char>=? c #\0) (char<=? c #\9))
944                (- (char->integer c) (char->integer #\0)))
945               ((and (char>=? c #\A) (char<=? c #\F))
946                (+ 10 (- (char->integer c) (char->integer #\A))))
947               ((and (char>=? c #\a) (char<=? c #\f))
948                (+ 10 (- (char->integer c) (char->integer #\a))))
949               (else
950                (syntax-error)))))
951              
952     (define (read-hex-byte)
953       (let* ((a (read-hex-nibble))
954              (b (read-hex-nibble)))
955         (+ b (* a 16))))
957     (if f
958         (begin
959           (let loop1 ()
960             (let ((c (read-char f)))
961               (cond ((not (char? c)))
962                     ((or (char=? c #\linefeed)
963                          (char=? c #\return))
964                      (loop1))
965                     ((not (char=? c #\:))
966                      (syntax-error))
967                     (else
968                      (let* ((len (read-hex-byte))
969                             (a1 (read-hex-byte))
970                             (a2 (read-hex-byte))
971                             (type (read-hex-byte)))
972                        (let* ((adr (+ a2 (* 256 a1)))
973                               (sum (+ len a1 a2 type)))
974                          (cond ((= type 0)
975                                 (let loop2 ((i 0))
976                                   (if (< i len)
977                                       (let ((a (+ adr (* hi16 65536)))
978                                             (b (read-hex-byte)))
979                                         (mem-store! a b)
980                                         (set! adr (modulo (+ adr 1) 65536))
981                                         (set! sum (+ sum b))
982                                         (loop2 (+ i 1))))))
983                                ((= type 1)
984                                 (if (not (= len 0))
985                                     (syntax-error)))
986                                ((= type 4)
987                                 (if (not (= len 2))
988                                     (syntax-error))
989                                 (let* ((a1 (read-hex-byte))
990                                        (a2 (read-hex-byte)))
991                                   (set! sum (+ sum a1 a2))
992                                   (set! hi16 (+ a2 (* 256 a1)))))
993                                (else
994                                 (syntax-error)))
995                          (let ((check (read-hex-byte)))
996                            (if (not (= (modulo (- sum) 256) check))
997                                (syntax-error)))
998                          (let ((c (read-char f)))
999                            (if (or (not (or (char=? c #\linefeed)
1000                                             (char=? c #\return)))
1001                                    (not (= type 1)))
1002                                (loop1)))))))))
1004           (close-input-port f)
1006           (mem->list))
1007         (begin
1008           (error "*** Could not open the HEX file")
1009           #f))))
1011 ;------------------------------------------------------------------------------
1013 (define (execute-hex-files . filenames)
1014   (let ((programs (map read-hex-file filenames)))
1015     (pic18-sim-setup)
1016     (for-each (lambda (prog)
1017                 (for-each (lambda (x) (set-rom (car x) (cdr x)))
1018                           prog))
1019               programs)
1020     (pic18-execute)
1021     (pic18-sim-cleanup)))
1023 (define (show-profiling-data) ;; TODO temporary solution until we have the true profile working
1024   (for-each (lambda (adr)
1025               (let ((count (vector-ref instrs-counts adr)))
1026                 (if (> count 0)
1027                     (print (list (number->string adr 16) "      "
1028                                  count "\n")))))
1029             (iota (vector-length instrs-counts))))
1030 (define (dump-profiling-data file)
1031   (with-output-to-file file show-profiling-data))
1033 ;; debugging procedures
1034 (define (add-break-point adr) (set! break-points (cons adr break-points)))
1035 (define (continue) (set! single-stepping-mode? #f)) ;; TODO + the equivalent of ,c