1 (define (linearize-and-cleanup cfg)
3 (define bbs-vector (cfg->vector cfg))
8 (set! todo (cons bb todo)))
13 (set! rev-code (cons instr rev-code)))
16 (emit (list 'movlw val)))
18 (emit (list 'movwf adr)))
20 (emit (list 'movfw adr)))
21 (define (movff src dst)
22 (emit (list 'movff src dst)))
25 (emit (list 'clrf adr)))
27 (emit (list 'setf adr)))
30 (emit (list 'incf adr)))
32 (emit (list 'decf adr)))
35 (emit (list 'addwf adr)))
37 (emit (list 'addwfc adr)))
40 (emit (list 'subwf adr)))
42 (emit (list 'subwfb adr)))
45 (emit (list 'mullw adr)))
47 (emit (list 'mulwf adr)))
50 (emit (list 'andwf adr)))
52 (emit (list 'iorwf adr)))
54 (emit (list 'xorwf adr)))
57 (emit (list 'rlcf adr)))
59 (emit (list 'rrcf adr)))
62 (emit (list 'bcf adr bit)))
64 (emit (list 'bsf adr bit)))
66 (emit (list 'btg adr bit)))
69 (emit (list 'comf adr)))
71 (define (tblrd) ;; TODO support the different modes
75 (emit (list 'cpfseq adr)))
77 (emit (list 'cpfslt adr)))
79 (emit (list 'cpfsgt adr)))
82 (emit (list 'bra label)))
85 (emit (list 'rcall label)))
88 (if (and #f (and (not (null? rev-code))
89 (eq? (caar rev-code) 'rcall)))
90 (let ((label (cadar rev-code)))
91 (set! rev-code (cdr rev-code))
93 (emit (list 'return))))
96 (if (and #f (and (not (null? rev-code))
97 (eq? (caar rev-code) 'bra)
98 (eq? (cadar rev-code) lab)))
100 (set! rev-code (cdr rev-code))
102 (emit (list 'label lab))))
105 (emit (list 'sleep)))
107 (define (move-reg src dst)
116 ;; takes 2 cycles (as much as movfw src ; movwf dst), but takes
117 ;; only 1 instruction
120 (define (bb-linearize bb)
121 (let ((label-num (bb-label-num bb)))
122 (let ((bb (vector-ref bbs-vector label-num)))
124 (define (move-lit n adr)
133 (define (dump-instr instr)
134 (cond ((call-instr? instr)
135 (let* ((def-proc (call-instr-def-proc instr))
136 (entry (def-procedure-entry def-proc)))
140 (let ((label (bb-label entry)))
143 ((return-instr? instr)
146 (let ((src1 (instr-src1 instr))
147 (src2 (instr-src2 instr))
148 (dst (instr-dst instr)))
149 (if (and (or (not (byte-cell? dst))
151 (or (not (byte-cell? src1))
152 (byte-cell-adr src1))
153 (or (not (byte-cell? src2))
154 (byte-cell-adr src2)))
156 (case (instr-id instr)
160 (let ((n (byte-lit-val src1))
161 (z (byte-cell-adr dst)))
163 (let ((x (byte-cell-adr src1))
164 (z (byte-cell-adr dst)))
169 (let ((n (byte-lit-val src2))
170 (z (byte-cell-adr dst)))
172 (move-lit (byte-lit-val src1) z)
173 (move-reg (byte-cell-adr src1) z))
174 (case (instr-id instr)
175 ((add) (cond ((= n 1) (incf z))
176 ((= n #xff) (decf z))
179 ((addc) (movlw n) (addwfc z))
180 ((sub) (cond ((= n 1) (decf z))
181 ((= n #xff) (incf z))
184 ((subb) (movlw n) (subwfb z))))
185 (let ((x (byte-cell-adr src1))
186 (y (byte-cell-adr src2))
187 (z (byte-cell-adr dst)))
188 (cond ((and (not (= x y))
190 (memq (instr-id instr)
192 ;; since this basically swaps the
193 ;; arguments, it can't be used for
198 ;; for subtraction, preserves argument
201 ;; this NEEDS to be done with movff, or
202 ;; else wreg will get clobbered and this
205 (else ;; TODO check if it could be merged with the previous case
208 (case (instr-id instr)
213 (else (error "..."))))))
215 ((mul) ; 8 by 8 multiplication
217 ;; since multiplication is commutative, the
218 ;; arguments are set up so the second one will
219 ;; be a literal if the operator is applied on a
220 ;; literal and a variable
221 (let ((n (byte-lit-val src2)))
223 (movlw (byte-lit-val src1))
224 (move-reg (byte-cell-adr src1) WREG))
225 ;; literal multiplication
227 (let ((x (byte-cell-adr src1))
228 (y (byte-cell-adr src2)))
233 ;; no instructions for bitwise operations involving
234 ;; literals exist on the PIC18
235 (let ((x (if (byte-lit? src1)
237 (byte-cell-adr src1)))
238 (y (if (byte-lit? src2)
240 (byte-cell-adr src2)))
241 (z (byte-cell-adr dst)))
242 (cond ((byte-lit? src1)
247 ((and (not (= x y)) (= y z))
252 (case (instr-id instr)
256 (else (error "...")))))
259 (let ((x (if (byte-lit? src1)
261 (byte-cell-adr src1)))
262 (z (byte-cell-adr dst)))
263 (cond ((byte-lit? src1) (move-lit x z))
264 ((not (= x z)) (move-reg x z)))
265 (case (instr-id instr)
271 (if (not (byte-lit? src2))
272 (error "bit offset must be a literal"))
273 (let ((x (byte-cell-adr src1))
274 (y (byte-lit-val src2)))
275 (case (instr-id instr)
278 ((toggle) (btg x y)))))
281 (let ((z (byte-cell-adr dst)))
283 (move-lit (byte-lit-val src1) z)
284 (move-reg (byte-cell-adr src1) z))
289 (move-lit (byte-lit-val src1) TBLPTRL)
290 (move-reg (byte-cell-adr src1) TBLPTRL))
292 (move-lit (byte-lit-val src2) TBLPTRH)
293 (move-reg (byte-cell-adr src2) TBLPTRH))
294 ;; TODO the 5 high bytes are not used for now
298 (if (null? (bb-succs bb))
299 (error "I think you might have given me an empty source file."))
300 (let* ((succs (bb-succs bb))
302 (bra (bb-label dest))
305 (let* ((succs (bb-succs bb))
306 (dest-true (car succs))
307 (dest-false (cadr succs)))
309 (define (compare flip adr)
310 (case (instr-id instr)
311 ((x<y) (if flip (cpfsgt adr) (cpfslt adr)))
312 ((x>y) (if flip (cpfslt adr) (cpfsgt adr)))
314 (bra (bb-label dest-false))
315 (bra (bb-label dest-true))
316 (add-todo dest-false)
317 (add-todo dest-true))
319 (cond ((byte-lit? src1)
320 (let ((n (byte-lit-val src1))
321 (y (byte-cell-adr src2)))
322 (if #f #;(and (or (= n 0) (= n 1) (= n #xff))
323 (eq? (instr-id instr) 'x==y))
324 (special-compare-eq-lit n x)
329 (let ((x (byte-cell-adr src1))
330 (n (byte-lit-val src2)))
331 (if #f #;(and (or (= n 0) (= n 1) (= n #xff))
332 (eq? (instr-id instr) 'x==y))
333 (special-compare-eq-lit n x)
338 (let ((x (byte-cell-adr src1))
339 (y (byte-cell-adr src2)))
344 (emit (list (instr-id instr))))))))))
348 (vector-set! bbs-vector label-num #f)
349 (label (bb-label bb))
350 (for-each dump-instr (reverse (bb-rev-instrs bb)))
351 (for-each add-todo (bb-succs bb)))))))
353 (let ((prog-label (asm-make-label 'PROG)))
358 (add-todo (vector-ref bbs-vector 0))
363 (let ((bb (car todo)))
364 (set! todo (cdr todo))
369 (define (assembler-gen filename cfg)
374 (movlw (cadr instr)))
376 (movwf (cadr instr)))
378 (movf (cadr instr) 'w))
380 (movff (cadr instr) (caddr instr)))
390 (addwf (cadr instr)))
392 (addwfc (cadr instr)))
394 (subwf (cadr instr)))
396 (subwfb (cadr instr)))
398 (mullw (cadr instr)))
400 (mulwf (cadr instr)))
402 (andwf (cadr instr)))
404 (iorwf (cadr instr)))
406 (xorwf (cadr instr)))
412 (bcf (cadr instr) (caddr instr)))
414 (bsf (cadr instr) (caddr instr)))
416 (btg (cadr instr) (caddr instr)))
420 (tblrd*)) ;; TODO support the other modes
422 (cpfseq (cadr instr)))
424 (cpfslt (cadr instr)))
426 (cpfsgt (cadr instr)))
428 (bra-or-goto (cadr instr)))
430 (rcall-or-call (cadr instr)))
435 (string-append (symbol->string (asm-label-id (cadr instr))) ":"))
436 (asm-label (cadr instr)))
440 (error "unknown instruction" instr))))
446 (let ((code (linearize-and-cleanup cfg)))
447 ; (pretty-print code)
448 (for-each gen code)))