OpenCores
URL https://opencores.org/ocsvn/igor/igor/trunk

Subversion Repositories igor

[/] [igor/] [trunk/] [microprogram_assembler/] [assembler.lisp] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 atypic
;;;
2
;;; Assembler!
3
;;;
4
 
5
(in-package #:mcasm)
6
 
7
(defvar *assembler-constants* (make-hash-table :test 'equal))
8
(defvar *assembler-labelnumbers* 0)
9
 
10
(defun next-labelnumber ()
11
  (incf *assembler-labelnumbers*))
12
 
13
(defstruct constant-info
14
  type
15
  name
16
  number)
17
 
18
(defun constant-info-to-string (info &key (key nil))
19
  (format nil "~A~A~A~A"
20
          (constant-info-type info)
21
          (if key
22
              "-"
23
              " ")
24
          (constant-info-name info)
25
          (if key ""
26
              (format nil " ~X" (constant-info-number info)))))
27
 
28
(defmacro def-const ((name number &key (type "const")) &body body)
29
  `(let ((info (make-constant-info :type ,type
30
                                   :name ',name
31
                                   :number ,number)))
32
     (setf (gethash (constant-info-to-string info :key nil) *assembler-constants*) info)
33
     ,@body))
34
 
35
(defmacro def-branch (name number)
36
  `(def-const (,name ,number :type "branch")
37
     (defparameter ,(intern (format nil "-BRANCH-~A-" name)) ,number)))
38
 
39
(def-branch O 1)
40
(def-branch C 2)
41
(def-branch N 4)
42
(def-branch Z 8)
43
(def-branch B 16)
44
 
45
(defmacro def-type (name number)
46
  `(def-const (,name ,number :type "type")
47
     (defparameter ,(intern (format nil "+TYPE-~A+" name)) ,number)))
48
 
49
(def-type none #x0)
50
(def-type int #x1)
51
(def-type float #x3)
52
(def-type cons #x4)
53
(def-type snoc #x5)
54
(def-type ptr #x6)
55
(def-type array #x7)
56
(def-type nil #x8)
57
(def-type t #x9)
58
(def-type char #xA)
59
(def-type symbol #xB)
60
(def-type function #xC)
61
(def-type builtin #xD)
62
 
63
(defparameter +n-regs+ #x400) ; number of registers
64
 
65
(defmacro defreg (name number)
66
  `(def-const (,name ,number :type "reg")
67
     (defparameter ,(intern (format nil "$~A" name)) ,number)))
68
 
69
(defmacro defmem (name number)
70
  `(def-const (,name ,number :type "memory")
71
     (defparameter ,(intern (format nil "%~A" name)) ,number)))
72
 
73
(defreg zero #x00)
74
(defreg one  #x01)
75
(defreg two  #x02)
76
 
77
(defreg s-addr #x03) ; address where an sframe has been stored
78
;;(defreg s-name #x04) ;; TODO do we want this?
79
;;(defreg s-fstack #x04)
80
(defreg s-condition #x04)
81
(defreg s-iterations #x05)
82
(defreg s-parent #x06)
83
 
84
;;(defreg e/f-addr #x07)
85
;;(defreg e/f-parent-addr #x08)
86
 
87
(defreg s-tmp  #x09)
88
(defreg e-tmp1 #x0A)
89
(defreg e-tmp2 #x0B)
90
(defreg e-tmp3 #x0C)
91
(defreg f-tmp1 #x0D)
92
(defreg f-tmp2 #x0E)
93
(defreg f-tmp3 #x0F)
94
 
95
;;(defreg e-addr #x09) ;; TODO remove this
96
(defreg e-expr #x10)
97
(defreg e-arg #x11)
98
(defreg e-result #x12)
99
(defreg e-phase #x13)
100
(defreg e-addr #x14)
101
 
102
;;(defreg f-addr #x15) ;; TODO remove this
103
(defreg f-func #x16)
104
(defreg f-env #x17)
105
;;(defreg f-estack #x18)
106
(defreg f-addr #x19)
107
 
108
(defreg alloc-addr #x20)
109
(defreg alloc-top #x21)
110
(defreg alloc-size #x22)
111
 
112
(defreg store-list-start #x23)
113
(defreg store-list-end #x24)
114
(defreg store-list-addr #x25)
115
(defreg store-list-reg #x26)
116
(defreg store-list-val #x27)
117
 
118
(defreg apply-result #x28)
119
(defreg apply-result-val #x29)
120
(defreg apply-func #x2A)
121
(defreg builtin-arg1 #x2B)
122
(defreg builtin-arg2 #x2C)
123
(defreg builtin-arg3 #x2D)
124
(defreg builtin-arg1-val #x2E)
125
(defreg builtin-arg2-val #x2F)
126
(defreg builtin-arg3-val #x30)
127
 
128
(defreg tmp-result #x33)
129
 
130
(defreg apply-argc #x34)
131
(defreg apply-required-argc #x35)
132
 
133
(defreg car #x40)
134
(defreg cdr #x41)
135
(defreg list-terminator #x42)
136
 
137
(defreg interrupt-tmp #x45)
138
 
139
(defreg params-car #x50)
140
(defreg args-car #x51)
141
(defreg apply-eval-expr #x52)
142
(defreg apply-eval-env #x53)
143
(defreg apply-apply-args #x54)
144
(defreg apply-apply-params #x55)
145
(defreg env #x56)
146
 
147
(defreg tmp1 #x57)
148
(defreg tmp2 #x58)
149
(defreg tmp3 #x59)
150
(defreg tmp4 #x5A)
151
 
152
(defreg fetch-args-arg-reg #x60)
153
(defreg fetch-args-arg #x61)
154
(defreg fetch-args-argval-reg #x62)
155
(defreg fetch-args-argval #x63)
156
(defreg fetch-args-arglist #x64)
157
 
158
(defreg io-devnr #x65)
159
(defreg io-new-devnr #x66)
160
(defreg io-mem-addr #x67)
161
 
162
(defreg message #x68)
163
(defreg message-shift #x69)
164
(defreg message-mask #x6A)
165
(defreg message-tmp1 #x6B)
166
(defreg message-tmp2 #x6C)
167
 
168
(defreg mc-stack-top #x090)
169
(defreg mc-stack-min #x091)
170
(defreg mc-stack-max #x09E)
171
 
172
(defreg e/f-top #x09F)
173
(defreg e/f-below-marker #x100)
174
(defreg e/f-min #x104)
175
(defreg e/f-min-expr #x104)
176
(defreg e/f-min-arg #x105)
177
(defreg e/f-min-result #x106)
178
(defreg e/f-min-phase #x107)
179
 
180
;; (defreg e/f-max-expr #x118)
181
;; (defreg e/f-max-arg #x119)
182
;; (defreg e/f-max-result #x11A)
183
;; (defreg e/f-max-phase #x11B)
184
;; (defreg e/f-max #x11B)
185
;; (defreg e/f-above-marker #x11C)
186
 
187
(defreg e/f-max-expr #x3F8)
188
(defreg e/f-max-arg #x3F9)
189
(defreg e/f-max-result #x3FA)
190
(defreg e/f-max-phase #x3FB)
191
(defreg e/f-max #x3FB)
192
(defreg e/f-above-marker #x3FC)
193
(defreg e/f-frame-size #x3FD)
194
 
195
(defreg init1                 #x3F0)
196
(defreg init2                 #x3F1)
197
(defreg init3                 #x3F2)
198
(defreg init-counter          #x3F3)
199
(defreg init-counter2         #x3F4)
200
(defreg init-shift1           #x3F5)
201
(defreg init-shift2           #x3F6)
202
(defreg init-char-mask        #x3F7)
203
(defreg init-chars-start      #x3F8)
204
(defreg init-symbol-addr      #x3F9)
205
(defreg init-symbol-str-addr  #x3FA)
206
(defreg init-symbol-char-addr #x3FB)
207
(defreg init-symbol-array     #x3FC)
208
 
209
;; needed variables (registers) for gc
210
 
211
;; register values that must be predefined
212
;; set these when testing gc standalone in emulator
213
(defreg gc-maxblocks #x70)      ;; total memory size
214
(defreg gc-spaces #x71)         ;; number of spaces we'll divide the memory in
215
(defreg gc-startofmem #x76)     ;; start of variable address space
216
 
217
;; registers set by evaluator before invoking gc
218
;; set these when testing gc standalone in emulator
219
(defreg gc-rootptr #x78)        ;; pointer to topmost object! hopefully
220
                                ;; there will be only one
221
 
222
;; registers set by init, keep these throughout
223
(defreg gc-spacesize #x72)      ;; size of each space: maxblocks / spaces
224
(defreg gc-sup #x73)            ;; first address beyond legal space:
225
                                ;; spaces * spacesize (NB: can be lower than
226
                                ;; maxblocks)
227
(defreg gc-gcspace #x74)        ;; start of gc exclusize space, sup - spacesize
228
 
229
;; registers used by everyone
230
(defreg gc-firstfree #x75)      ;; first free memory block
231
                                ;; (might exist already in other microcode)
232
 
233
;; scratch registers, can be used when gc is not running (but gc will
234
;; destroy them)
235
 
236
(defreg gc-1 #x80)              ;; temp
237
(defreg gc-vi #x83)
238
(defreg gc-t #x84)              ;; ptr-rev
239
(defreg gc-x #x85)              ;; ptr-rev
240
(defreg gc-y #x86)              ;; ptr-rev
241
(defreg gc-v #x87)              ;; ptr-rev
242
(defreg gc-followp #x88)        ;; ptr-rev
243
(defreg gc-cannext #x89)        ;; ptr-rev
244
(defreg gc-canprev #x8a)        ;; ptr-rev
245
 
246
(defreg gc-temp #x8b)
247
(defreg gc-mem #x8c)
248
(defreg gc-from #x84)           ;; at this stage we're no longer using
249
(defreg gc-to #x85)             ;; some of the above variables
250
(defreg gc-val #x86)
251
(defreg gc-temp2 #x87)
252
(defreg gc-baseaddr #x88)
253
 
254
(defreg gc-mem-limit #x7F)
255
 
256
;; div-variables (reusing gc-registers)
257
(defreg div-low #x88)
258
(defreg div-high #x89)
259
(defreg div-mid #x8a)
260
(defreg div-res #x8b)
261
(defreg div-sign #x8c)
262
(defreg mod-val1 #x87)
263
(defreg mod-val2 #x86)
264
 
265
(defparameter +gc-free+ #x00)
266
(defparameter +gc-used+ #x01)
267
 
268
(defparameter +gc-spaces+ #xA)
269
 
270
(defparameter +gc-limit+ #x1000) ; if free space is less than this, GC should be run
271
 
272
 
273
;; memory:
274
 
275
(defmem nil #x00)
276
(defmem t #x01)
277
(defmem if #x02)
278
(defmem quote #x03)
279
(defmem lambda #x04)
280
(defmem progn #x05)
281
 
282
(defparameter +first-builtin+ #x06)
283
(defmem cons #x06)
284
(defmem car #x07)
285
(defmem cdr #x08)
286
(defmem eval #x09)
287
(defmem apply #x0A)
288
(defmem type #x0B)
289
(defmem make-array #x0C)
290
(defmem array-size #x0D)
291
(defmem array-get #x0E)
292
(defmem array-set #x0F)
293
(defmem make-symbol #x10)
294
(defmem symbol-to-string #x11)
295
(defmem char-to-int #x12)
296
(defmem int-to-char #x13)
297
(defmem get-char #x14)
298
(defmem put-char #x15)
299
(defmem num-devices #x16)
300
(defmem device-type #x17)
301
(defmem set-address #x18)
302
(defmem get-address #x19)
303
(defmem error #x1A)
304
(defmem add #x1B)
305
(defmem sub #x1C)
306
(defmem mul #x1D)
307
(defmem div #x1E)
308
(defmem bitwise-and #x1F)
309
(defmem bitwise-or #x20)
310
(defmem bitwise-not #x21)
311
(defmem bitwise-shift #x22)
312
(defmem current-environment #x23)
313
(defmem make-eval-state #x24)
314
(defmem eval-partial #x25)
315
(defmem define #x26)
316
(defmem undefine #x27)
317
(defmem eq? #x28)
318
(defmem num-eq? #x29)
319
(defmem char-eq? #x2A)
320
(defmem less-than? #x2B)
321
(defmem mod #x2C)
322
(defmem set! #x2D)
323
(defmem set-car! #x2E)
324
(defmem set-cdr! #x2F)
325
(defmem function-data #x30)
326
(defmem builtin-name #x31)
327
(defmem device-size #x32)
328
(defmem device-status #x33)
329
(defparameter +last-builtin+ %device-status)
330
(defparameter +first-magic-var+ +first-builtin+)
331
(defparameter +last-magic-var+ +last-builtin+)
332
 
333
(defmem symbol-table #x3F)
334
(defparameter +first-phase+ #x40)
335
(defmem phase-eval #x40)
336
(defmem phase-eval-args #x41)
337
(defmem phase-apply #x42)
338
(defmem phase-eval-if #x43)
339
(defmem phase-initial #x44)
340
(defmem phase-env-lookup #x45)
341
(defmem phase-env-lookup-local #x46)
342
(defmem phase-apply-function #x47)
343
(defmem phase-bind-args #x48)
344
(defmem phase-eval-progn #x49)
345
(defmem phase-eval-args-top #x4A)
346
(defmem phase-eval-args-cdr #x4B)
347
(defmem phase-eval-args-cons #x4C)
348
(defmem phase-eval-symbol #x4D)
349
(defmem phase-set! #x4E)
350
(defparameter +last-phase+ %phase-set!)
351
 
352
(defmem timeout #x50)
353
(defmem err-invalid-phase #x51)
354
(defmem err-unbound-symbol #x52)
355
(defmem err-invalid-param-list #x53)
356
(defmem err-too-few-args #x54)
357
(defmem err-too-many-args #x55)
358
(defmem err-invalid-state #x56)
359
(defmem err-invalid-arg-list #x57)
360
(defmem err-type-error #x58)
361
(defmem err-not-a-list #x59)
362
(defmem err-not-a-function #x5A)
363
(defmem err-invalid-function #x5B)
364
(defmem err-malformed-form #x5C)
365
(defmem err-invalid-builtin #x5D)
366
(defmem err-invalid-array-index #x5E)
367
(defmem err-invalid-env #x5F)
368
(defmem err-not-a-pair #x60)
369
(defmem err-io-error #x61)
370
(defmem err-division-by-zero #x62)
371
(defmem err-overflow #x63)
372
(defparameter +last-symbol+ %err-overflow)
373
 
374
(defmem area-builtins #x100)
375
(defmem area-chars    #x200)
376
(defmem area-ints     #x280)
377
(defmem area-strings  #x300)
378
(defmem area-symlist  #xE00)
379
 
380
(defparameter +constant-chars+ (- %area-ints %area-chars))
381
(defparameter +constant-ints+ (- %area-strings %area-ints))
382
 
383
(defmem memory-root #xFFE)
384
(defmem mem-reserved-top #x1000)
385
(defmem boot-prog-start %mem-reserved-top)
386
 
387
(defparameter +memory-size+ (* 2 (* 1024 1024)))
388
 
389
(defmem io-mem-addr  #x3FFFF00) ; TODO too large for immediate value
390
(defmem io-devices        #x00)
391
(defmem io-curdev         #x01)
392
(defmem io-cli            #x02)
393
(defmem io-sai            #x03)
394
(defmem io-intrdev        #x04)
395
(defmem io-object         #x10)
396
(defmem io-addr-l         #x11)
397
(defmem io-addr-h         #x12)
398
(defmem io-size-l         #x13)
399
(defmem io-size-h         #x14)
400
(defmem io-status         #x15)
401
(defmem io-identification #x16)
402
(defmem io-irqenable      #x17)
403
 
404
(defparameter +dev-boot+ #x03)
405
(defparameter +dev-serial+ #x00)
406
 
407
 
408
;;; Helper functions
409
 
410
;; Convert a argument to the argument type
411
(defun argument-to-type (arg)
412
  (typecase arg
413
    (integer 'imm)
414
    (keyword 'label)
415
    (t 'other)))
416
 
417
;; Make the instruction
418
;; Only set the opcode
419
(defun make-inst-opcode (opcode &key (debug 0) (break 0))
420
  (let ((inst 0))
421
    (setf (ldb (byte 6 42) inst) opcode)
422
    (setf (ldb (byte 1 41) inst) debug)
423
    (setf (ldb (byte 1 40) inst) break)
424
    inst))
425
 
426
;; Parse an integer symbol and return the register number
427
(defun reg-to-num (reg)
428
  (typecase reg
429
    (symbol
430
     (parse-integer (subseq (format nil "~A" reg) 1)))
431
    (integer
432
     reg)))
433
 
434
(defmacro rewrite-inst-part (inst &key from size value)
435
  `(setf (ldb (byte ,size ,from) ,inst) ,value))
436
 
437
;; Make a function that returnes the binary representation of an instruction
438
(defmacro set-instruction ((&rest rest) &body body)
439
  (let ((opcodevar (gensym))
440
        (debugvar (gensym))
441
        (instvar (gensym))
442
        (breakvar (gensym)))
443
    `(lambda (,opcodevar ,@rest &key (,debugvar 0) (,breakvar 0))
444
       (let ((,instvar (make-inst-opcode ,opcodevar :debug ,debugvar :break ,breakvar)))
445
         ,@(loop for part in body
446
              collect (cons 'rewrite-inst-part (cons instvar part)))
447
         ,instvar))))
448
 
449
;; The different opcode formats
450
(defparameter +opcodeformats+
451
  `(
452
    (noarg . (() ,(set-instruction ())))
453
    (mem . ((r r imm) ,(set-instruction (r1 r2 imm)
454
                                        (:size 11 :from 29 :value (reg-to-num r1))
455
                                        (:size 11 :from 18 :value (reg-to-num r2))
456
                                        (:size 18 :from 0 :value imm))))
457
    (data . ((r r) ,(set-instruction (r1 r2)
458
                                         (:size 11 :from 29 :value (reg-to-num r1))
459
                                         (:size 11 :from 18 :value (reg-to-num r2)))))
460
    (dataimm . ((r imm) ,(set-instruction (r1 imm)
461
                                            (:size 11 :from 29 :value (reg-to-num r1))
462
                                            ;(:size 11 :from 18 :value (reg-to-num r2))
463
                                            (:size 29 :from 0 :value imm))))
464
    (onereg . ((r) ,(set-instruction (r1)
465
                                     (:size 11 :from 29 :value (reg-to-num r1)))))
466
    (alu . ((r r) ,(set-instruction (r1 r2)
467
                                      (:size 11 :from 29 :value (reg-to-num r1))
468
                                      (:size 11 :from 18 :value (reg-to-num r2)))))
469
    (argtype0 . ((imm) ,(set-instruction (imm)
470
                                         (:size 40 :from 0 :value imm))))
471
    (argtype1 . ((r imm) ,(set-instruction (r1 imm)
472
                                           (:size 11 :from 29 :value (reg-to-num r1))
473
                                           (:size 29 :from 0 :value imm))))
474
    (branch . ((r imm imm imm) ,(set-instruction (r1 mask flag addr)
475
                                                 (:size 11 :from 29 :value (reg-to-num r1))
476
                                                 (:size 8 :from 21 :value mask)
477
                                                 (:size 8 :from 13 :value flag)
478
                                                 (:size 13 :from 0 :value addr))))
479
    ))
480
 
481
;; Get the function from a format type
482
(defun get-format-function (format)
483
  (second (cdr (assoc format +opcodeformats+))))
484
 
485
;; Add an instruction to the list
486
(defun add-instruction (opcode args function)
487
  (setf *pre-assembly-data*
488
        (append
489
         (list (list opcode args function))
490
         *pre-assembly-data*)))
491
 
492
;; Define an instruction
493
;; The generated function returns a list that contains the opcode,
494
;; the arguments and the function that makes the bit representation.
495
(defmacro make-instruction (name format opcode)
496
  `(defun ,(intern (format nil "%~A" name)) (&rest args)
497
     (when (eq *assembler-state* :gather)
498
       (incf *assembler-position*))
499
     (let ((f (cdr (assoc ',format +opcodeformats+))))
500
       (when (not f)
501
         (error "Missing opcode group for ~A for instruction ~A" ',format ',name))
502
       (add-instruction ,opcode args f))))
503
 
504
;; Write a 48bit binary value to a stream
505
(defun write-48bit-unsigned (value s)
506
  (write-byte (ldb (byte 8 40) value) s)
507
  (write-byte (ldb (byte 8 32) value) s)
508
  (write-byte (ldb (byte 8 24) value) s)
509
  (write-byte (ldb (byte 8 16) value) s)
510
  (write-byte (ldb (byte 8 8) value) s)
511
  (write-byte (ldb (byte 8 0) value) s))
512
 
513
;; Assemble our instructions
514
(defun assemble-it (pre-assembly stream &key output-format simulator-lines)
515
  (let ((pre-assembly (copy-tree (reverse pre-assembly))))
516
    ;; Assemble and write out
517
    (format t "Writing out assembly~%")
518
    (let ((instructions (loop for a in pre-assembly
519
                           unless (labelp a)
520
                           collect (apply (second (third a)) (first a) (second a)))))
521
      (let ((number-of-instructions (length instructions)))
522
        (dolist (inst instructions)
523
          (cond ((eq output-format :human-readable)
524
                 (format stream "~12,'0X -- ~48,'0B~%" inst inst))
525
                ((eq output-format :simulator)
526
                 (format stream "~48,'0B~%" inst))
527
                (t
528
                 (write-48bit-unsigned inst stream))))
529
        (when simulator-lines
530
          (dotimes (i (- simulator-lines number-of-instructions))
531
            (format stream "~48,'0B~%" 0)))))))
532
 
533
;; Empty assembler cache
534
(defun reset-assembler ()
535
  (setf *pre-assembly-data* (list)))
536
 
537
;;; Setup instructions and reset the assembler
538
(defun setup-assembler ()
539
  (make-instruction nop noarg #x00)
540
  (make-instruction halt noarg #x01)
541
 
542
  ;; ALU
543
  (make-instruction add alu #x02)
544
  (make-instruction sub alu #x03)
545
  (make-instruction mul alu #x04)
546
  (make-instruction div alu #x05)
547
  (make-instruction and alu #x06)
548
  (make-instruction or alu #x07)
549
  (make-instruction xor alu #x08)
550
  (make-instruction not alu #x09)
551
  (make-instruction shift-l alu #x0A)
552
  (make-instruction mod alu #x0B)
553
  (make-instruction shift-r alu #x0C)
554
 
555
  ;; Memory
556
  (make-instruction load mem #x10)
557
  (make-instruction store mem #x11)
558
 
559
  ;; Branch
560
  (make-instruction branch branch #x16)
561
 
562
  ;; Status
563
  (make-instruction set-flag argtype1 #x17)
564
  (make-instruction clear-flag argtype0 #x18)
565
  (make-instruction get-flag argtype1 #x19)
566
 
567
  ;; Data
568
  (make-instruction get-type data #x20)
569
  (make-instruction set-type data #x21)
570
  (make-instruction set-type-imm dataimm #x22)
571
 
572
  (make-instruction set-datum data #x23)
573
  (make-instruction set-datum-imm dataimm #x24)
574
 
575
  (make-instruction get-gc data #x25)
576
  (make-instruction set-gc data #x26)
577
  (make-instruction set-gc-imm dataimm #x27)
578
 
579
  (make-instruction cpy data #x28)
580
 
581
  ;; Compare
582
  (make-instruction cmp-type data #x29)
583
  (make-instruction cmp-type-imm dataimm #x2A)
584
  (make-instruction cmp-datum data #x2B)
585
  (make-instruction cmp-datum-imm dataimm #x2C)
586
  (make-instruction cmp-gc data #x2D)
587
  (make-instruction cmp-gc-imm dataimm #x2E)
588
  (make-instruction cmp data #x2F)
589
 
590
  ;; Leds
591
  (make-instruction set-leds onereg #x3F)
592
 
593
  (reset-assembler)
594
 
595
  t)
596
 
597
;; Info gathering or assembling state
598
;; The first get labels information and so on, the second assemble correct instructions
599
(defvar *assembler-state*)
600
(defvar *assembler-labels*)
601
(defvar *assembler-position*)
602
 
603
;; Debug functions
604
 
605
;; Write labels
606
(defun write-labels (file labels)
607
  (format t "Writing out label information~%")
608
  (with-open-file (s
609
                   (concatenate 'string file ".labels")
610
                   :element-type 'character
611
                   :direction :output
612
                   :if-does-not-exist :create
613
                   :if-exists :supersede)
614
    (maphash
615
     (lambda (key value)
616
       (format s "~A ~X~%" key value))
617
     labels)))
618
 
619
;; Write constant information
620
(defun write-constants (file constants labels)
621
  (format t "Writing constant information~%")
622
  (with-open-file (s
623
                   (concatenate 'string file ".const")
624
                   :element-type 'character
625
                   :direction :output
626
                   :if-does-not-exist :create
627
                   :if-exists :supersede)
628
    (maphash
629
     (lambda (key value)
630
       (format s "label ~A ~X~%" key value))
631
     labels)
632
    (maphash (lambda (key value)
633
               (declare (ignore key))
634
               (format s "~A~%" (constant-info-to-string value)))
635
             constants)))
636
 
637
;; The main assembly macro
638
;; Adds inst-prefixes and fixes labels
639
(defmacro with-assembly ((outfile &key output-format simulator-lines) &body body)
640
  (let ((streamvar (gensym "STREAM")))
641
    `(let ((*assembler-labels* (make-hash-table))
642
           (*assembler-state* :gather)
643
           (*assembler-position* 0))
644
       (setf *assembler-labelnumbers* 0)
645
       ,@(loop
646
            for inst in (copy-tree body)
647
            when (not (labelp inst))
648
            collect (rewrite-instruction inst :gather)
649
            when (labelp inst)
650
            collect `(setf (gethash ,inst *assembler-labels*) *assembler-position*))
651
       (setf *assembler-labelnumbers* 0)
652
       (format t "We got ~D instructions~%" *assembler-position*)
653
       (with-open-file (,streamvar ,outfile
654
                                   :element-type ,(cond ((or (eq output-format :human-readable)
655
                                                             (eq output-format :simulator))
656
                                                         ''character)
657
                                                        (t ''unsigned-byte))
658
                                   :direction :output
659
                                   :if-does-not-exist :create
660
                                   :if-exists :supersede)
661
         (setf *assembler-state* :assemble)
662
         (reset-assembler)
663
         ,@(loop
664
              for inst in body
665
              when (not (labelp inst))
666
              collect (rewrite-instruction inst :assemble))
667
         ;; Write out assembled exectuable
668
         (assemble-it *pre-assembly-data* ,streamvar :output-format ,output-format :simulator-lines ,simulator-lines)
669
         ;; Output debug info
670
         (write-constants ,outfile *assembler-constants* *assembler-labels*)
671
         (write-labels ,outfile *assembler-labels*)))))
672
 
673
;;; Microcode instructions
674
 
675
(defmacro with-new-label ((prefix var) &body body)
676
  `(let ((,var (intern (format nil "~A-~A" (string-upcase ,prefix) (next-labelnumber)) (find-package "KEYWORD"))))
677
     ,@body))
678
 
679
(defmacro force-label (label)
680
  `(when (labelp ,label)
681
     (if (eq *assembler-state* :gather)
682
         (setf ,label 0)
683
         (progn
684
           (unless (gethash ,label *assembler-labels*)
685
             (error "Unknown label: ~A" ,label))
686
           (setf ,label (gethash ,label *assembler-labels*))))))
687
 
688
(defmacro with-force-label ((label) &body body)
689
  (if (integerp label)
690
      `(progn
691
         ,@body)
692
      `(let ((,label ,label))
693
         (force-label ,label)
694
         ,@body)))
695
 
696
(defmacro with-force-label* ((var label) &body body)
697
  `(let ((,var ,label))
698
     (force-label ,var)
699
     ,@body))
700
 
701
(defmacro %when (comparison &body body)
702
  `(with-new-label ("when" end)
703
     ,comparison
704
     (branchimm-false end)
705
     ,@body
706
     (make-label end)))
707
 
708
(defmacro %when-not (comparison &body body)
709
  `(with-new-label ("when" end)
710
     ,comparison
711
     (branchimm end)
712
     ,@body
713
     (make-label end)))
714
 
715
(defmacro when= ((r1 r2) &body body)
716
  `(with-new-label ("when=" end)
717
     (%cmp-datum ,r1 ,r2)
718
     (branchimm-false end)
719
     ,@body
720
     (make-label end)))
721
 
722
(defmacro when!= ((r1 r2) &body body)
723
  `(with-new-label ("when=" end)
724
     (%cmp-datum ,r1 ,r2)
725
     (branchimm end)
726
     ,@body
727
     (make-label end)))
728
 
729
(defun some-stuff ()
730
  (make-integer 3 4)
731
  (make-integer 4 4)
732
  (when= (3 4)
733
    (make-integer 5 4)))
734
 
735
;; Make a indirect register
736
(defun indirect-register (reg)
737
  (let ((i reg))
738
    (setf (ldb (byte 1 10) i) 1)
739
    i))
740
 
741
;; Branch
742
 
743
(defmacro %branch* (reg offset &rest flags)
744
  (let ((maskvar (gensym))
745
        (flagvar (gensym)))
746
    `(let ((,maskvar (funcall #'logior ,@(loop for flag in flags
747
                                            collect (intern (format nil "-BRANCH-~A-" (if (listp flag) (cadr flag) flag))))))
748
           (,flagvar (funcall #'logior ,@(loop for flag in flags
749
                                            when (not (listp flag))
750
                                            collect (intern (format nil "-BRANCH-~A-" flag))))))
751
       (%branch ,reg ,maskvar ,flagvar ,offset))))
752
 
753
(defun branchimm* (mask flag addr)
754
  (with-force-label (addr) ;; Hack to fix labels in a few places, sorry about this.
755
    (%branch $zero mask flag addr)))
756
 
757
;; Immediate branch true
758
(defun branchimm (addr)
759
  (branchimm* #x8 #x8 addr))
760
 
761
;; Immediate branch false
762
(defun branchimm-false (addr)
763
  (branchimm* #x8 0 addr))
764
 
765
;; Jmp
766
(defun jump (r addr)
767
  (with-force-label (addr)
768
    (%branch r 0 0 addr)))
769
 
770
(defun jump-imm (addr)
771
  (with-force-label (addr)
772
    (jump $zero addr)))
773
 
774
(defun jump-reg (r)
775
  (jump r 0))
776
 
777
(defun make-object-imm (reg type value)
778
  (%set-type-imm reg type)
779
  (%set-datum-imm reg value))
780
 
781
(defun make-integer (reg value)
782
  (make-object-imm reg +type-int+ value))
783
 
784
(defun %add* (d a b)
785
  (%cpy d a)
786
  (%add d b))
787
 
788
(defun %sub* (d a b)
789
  (%cpy d a)
790
  (%sub d b))
791
 
792
(defun %mul* (d a b)
793
  (%cpy d a)
794
  (%mul d b))
795
 
796
(defun %div* (d a b)
797
  (%cpy d a)
798
  (%div d b))
799
 
800
(defun %mod* (d a b)
801
  (%cpy d a)
802
  (%mod d b))
803
 
804
(defun %and* (d a b)
805
  (%cpy d a)
806
  (%and d b))
807
 
808
(defun %or* (d a b)
809
  (%cpy d a)
810
  (%or d b))
811
 
812
(defun %incr (reg)
813
  (%add reg $one))
814
 
815
(defun %decr (reg)
816
  (%sub reg $one))
817
 
818
(defun labeltest ()
819
  (let ((label (gensym "IF-")))
820
    (make-integer 10 #x5)
821
    (make-label (intern (format nil "~A" label) (find-package "KEYWORD")))))
822
 
823
#|
824
;; Another simple test function
825
;; Suppose to be used to define the real API the assembler will have
826
(defun test-set2 ()
827
  (with-assembly ("/tmp/microcode" :output-format :simulator :simulator-lines 100)
828
    (make-integer 3 4)
829
    (make-integer 4 4)
830
    (when= (3 4)
831
      (make-integer 5 4))
832
    (when!= (3 4)
833
      (make-integer 6 4))))
834
|#
835
 
836
;; Make microcode instruction functions
837
(setup-assembler)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.