Fixed the new lexer.
[m68k-assembler.git] / machine.lisp
blobb8e39738df694dd849132d310d4ebb492a6aea66
1 ;;; Tables and things which are truly machine (m68k) specific.
2 ;;;
3 ;;; Julian Squires/2005
5 (in-package :m68k-assembler)
7 (let ((all-ea-modes '(immediate pc-index pc-displacement absolute-long absolute-short
8 postincrement-indirect predecrement-indirect displacement-indirect
9 indexed-indirect vanilla-indirect address-register data-register)))
10 (defparameter *constraints-modes-table*
11 `((all-ea-modes ,all-ea-modes)
12 (alterable-modes
13 ,(set-difference all-ea-modes
14 '(immediate pc-index pc-displacement)))
15 (data-alterable-modes
16 ,(set-difference all-ea-modes
17 '(immediate pc-index pc-displacement address-register)))
18 (memory-alterable-modes
19 ,(set-difference all-ea-modes
20 '(immediate pc-index pc-displacement address-register data-register)))
21 (data-addressing-modes
22 ,(set-difference all-ea-modes '(address-register)))
23 (control-addressing-modes
24 ,(set-difference all-ea-modes
25 '(address-register data-register immediate predecrement-indirect
26 postincrement-indirect)))
27 (movem-pre-modes (vanilla-indirect predecrement-indirect
28 displacement-indirect indexed-indirect absolute-short
29 absolute-long))
30 (movem-post-modes (vanilla-indirect postincrement-indirect
31 displacement-indirect indexed-indirect absolute-short
32 absolute-long pc-displacement pc-index))
33 (absolute (absolute-short absolute-long)))
34 "Table of mode names used in *ASM-OPCODE-TABLE* for constraint matching."))
36 (defparameter *asm-opcode-table*
37 ;; first field is the opcode name, sans modifiers. remaining fields
38 ;; are either pairs of operand constraints and code generation
39 ;; masks, or functions. these are matched or called in sequence,
40 ;; until one can be found which matches.
42 ;; Code generation masks are lists in the form: (size code) where
43 ;; size indicates the number of bits this part should take up, and
44 ;; code is the code to evaluate when generating this part of the
45 ;; expression. (Actually, code should be a function call, now.)
46 ;; The list starts from the most significant bit of the instruction
47 ;; word and moves down. SIZE fields of ? indicate a variable size,
48 ;; where the code in question will return a suitable size value as a
49 ;; second value.
50 `(,@(mapcar
51 (lambda (x)
52 `(,x
53 (((byte) (data-register) (data-register)) .
54 ((4 ,(if (string= x "ABCD") #b1101 #b1001))
55 (3 (register-idx second-operand)) (6 #b100000)
56 (3 (register-idx first-operand))))
57 (((byte) (predecrement-indirect) (predecrement-indirect))
58 ((4 ,(if (string= x "ABCD") #b1101 #b1001))
59 (3 (register-idx second-operand)) (6 #b100001)
60 (3 (register-idx first-operand))))))
61 '("ABCD" "SBCD"))
63 ,@(mapcan
64 (lambda (x)
65 `((,x
66 ,(concatenate 'string x "I") ; I and Q are faster.
67 ,(concatenate 'string x "Q")
68 (((byte word long) (all-ea-modes) (data-register))
69 ((4 ,(if (string= x "ADD") #b1101 #b1001))
70 (3 (register-idx second-operand)) (1 #b0)
71 (2 (modifier-bits modifier))
72 (6 (effective-address-mode first-operand modifier))
73 (? (effective-address-extra first-operand modifier))))
74 (((byte word long) (data-register) (memory-alterable-modes))
75 ((4 ,(if (string= x "ADD") #b1101 #b1001))
76 (3 (register-idx first-operand)) (1 #b1)
77 (2 (modifier-bits modifier))
78 (6 (effective-address-mode second-operand modifier))
79 (? (effective-address-extra second-operand modifier))))
80 ,(concatenate 'string x "A")
81 ,(concatenate 'string x "X"))
82 (,(concatenate 'string x "A")
83 (((word long) (all-ea-modes) (address-register))
84 ((4 ,(if (string= x "ADD") #b1101 #b1001))
85 (3 (register-idx second-operand))
86 (3 (if-eql-word-p modifier #b011 #b111))
87 (6 (effective-address-mode first-operand modifier))
88 (? (effective-address-extra first-operand modifier)))))
89 (,(concatenate 'string x "I")
90 (((byte word long) (immediate) (data-alterable-modes))
91 ((8 ,(if (string= x "ADD") #b00000110 #b00000100))
92 (2 (modifier-bits modifier))
93 (6 (effective-address-mode second-operand modifier))
94 (? (immediate-value first-operand modifier))
95 (? (effective-address-extra second-operand modifier)))))
96 (,(concatenate 'string x "Q")
97 (((byte word long) (immediate (<= 1 value 8)) (alterable-modes))
98 ((4 #b0101) (3 (addq-immediate-value first-operand))
99 (1 ,(if (string= x "ADD") 0 1))
100 (2 (modifier-bits modifier))
101 (6 (effective-address-mode second-operand modifier))
102 (? (effective-address-extra second-operand modifier)))))
103 (,(concatenate 'string x "X")
104 (((byte word long) (data-register) (data-register))
105 ((4 ,(if (string= x "ADD") #b1101 #b1001))
106 (3 (register-idx second-operand)) (1 #b1)
107 (2 (modifier-bits modifier))
108 (3 #b000) (3 (register-idx first-operand))))
109 (((byte word long) (predecrement-indirect) (predecrement-indirect))
110 ((4 #b1101) (3 (register-idx second-operand)) (1 #b1)
111 (2 (modifier-bits modifier))
112 (3 #b001) (3 (register-idx first-operand)))))))
113 '("ADD" "SUB"))
115 ,@(mapcan
116 (lambda (x)
117 `((,x
118 ,(concatenate 'string x "I") ; I is usually faster.
119 ,@(unless (string= x "EOR")
120 `((((byte word long) (data-addressing-modes) (data-register))
121 ((4 ,(cond ((string= x "AND") #b1100)
122 ((string= x "OR") #b1000)))
123 (3 (register-idx second-operand)) (1 #b0)
124 (2 (modifier-bits modifier))
125 (6 (effective-address-mode first-operand modifier))
126 (? (effective-address-extra first-operand modifier))))))
127 (((byte word long) (data-register) ,(if (string= x "EOR")
128 `(data-alterable-modes)
129 `(memory-alterable-modes)))
130 ((4 ,(cond ((string= x "AND") #b1100)
131 ((string= x "EOR") #b1011)
132 ((string= x "OR") #b1000)))
133 (3 (register-idx first-operand)) (1 #b1)
134 (2 (modifier-bits modifier))
135 (6 (effective-address-mode second-operand modifier))
136 (? (effective-address-extra second-operand modifier)))))
137 (,(concatenate 'string x "I")
138 (((byte word long) (immediate) (data-alterable-modes))
139 ((4 #b0000)
140 (4 ,(cond ((string= x "AND") #b0010)
141 ((string= x "EOR") #b1010)
142 ((string= x "OR") #b0000)))
143 (2 (modifier-bits modifier))
144 (6 (effective-address-mode second-operand modifier))
145 (? (immediate-value first-operand modifier))
146 (? (effective-address-extra second-operand modifier))))
147 (((byte) (immediate) (register (string-equal value "CCR")))
148 ((4 #b0000)
149 (4 ,(cond ((string= x "AND") #b0010)
150 ((string= x "EOR") #b1010)
151 ((string= x "OR") #b0000)))
152 (16 #b0011110000000000)
153 (8 (immediate-value first-operand 'byte))))
154 (((word) (immediate) (register (string-equal value "SR")))
155 ((4 #b0000)
156 (4 ,(cond ((string= x "AND") #b0010)
157 ((string= x "EOR") #b1010)
158 ((string= x "OR") #b0000)))
159 (8 #b01111100)
160 (16 (immediate-value first-operand 'word)))))))
161 '("AND" "EOR" "OR"))
163 ,@(mapcar
164 (lambda (x)
165 `(,x
166 (((byte word long) (data-register) (data-register))
167 ((4 #b1110) (3 (register-idx first-operand))
168 (1 ,(if (string= x "L" :start1 (1- (length x))) 1 0))
169 (2 (modifier-bits modifier))
170 (3 ,(cond ((string= x "LS" :end1 2) #b101)
171 ((string= x "AS" :end1 2) #b100)
172 ((string= x "ROX" :end1 3) #b110)
173 (t #b111)))
174 (3 (register-idx second-operand))))
175 (((byte word long) (immediate (<= 1 value 8)) (data-register))
176 ((4 #b1110) (3 (addq-immediate-value first-operand))
177 (1 ,(if (string= x "L" :start1 (1- (length x))) 1 0))
178 (2 (modifier-bits modifier))
179 (3 ,(cond ((string= x "LS" :end1 2) #b001)
180 ((string= x "AS" :end1 2) #b000)
181 ((string= x "ROX" :end1 3) #b010)
182 (t #b011)))
183 (3 (register-idx second-operand))))
184 (((byte word long) (memory-alterable-modes))
185 ((5 #b11100)
186 (2 ,(cond ((string= x "LS" :end1 2) #b01)
187 ((string= x "AS" :end1 2) #b00)
188 ((string= x "ROX" :end1 3) #b10)
189 (t #b11)))
190 (1 ,(if (string= x "L" :start1 (1- (length x))) 1 0))
191 (2 #b11) (6 (effective-address-mode first-operand modifier))
192 (? (effective-address-extra first-operand modifier))))))
193 '("ASL" "ASR" "LSL" "LSR" "ROL" "ROR" "ROXL" "ROXR"))
195 ,@(mapcar
196 (lambda (x)
197 `(,(car x)
198 (((byte word) (absolute))
199 ((4 #b0110) (4 ,(cdr x))
200 (? (branch-displacement-bits first-operand modifier))))))
201 '(("BCC" . #b0100) ("BCS" . #b0101) ("BEQ" . #b0111) ("BGE" . #b1100)
202 ("BGT" . #b1110) ("BHI" . #b0010) ("BLE" . #b1111) ("BLS" . #b0011)
203 ("BLT" . #b1101) ("BMI" . #b1011) ("BNE" . #b0110) ("BPL" . #b1010)
204 ("BVC" . #b1000) ("BVS" . #b1001) ("BRA" . #b0000) ("BSR" . #b0001)))
206 ,@(mapcar
207 (lambda (x)
208 `(,(car x)
209 (((byte long) (data-register) (data-alterable-modes))
210 ((4 #b0000) (3 (register-idx first-operand))
211 (1 #b1) (2 ,(cdr x))
212 (6 (effective-address-mode second-operand modifier))
213 (? (effective-address-extra second-operand modifier))))
214 (((byte long) (immediate) (data-alterable-modes))
215 ((8 #b00001000) (2 ,(cdr x))
216 (6 (effective-address-mode second-operand modifier))
217 (8 #b00000000) (8 (immediate-value first-operand 'byte))
218 (? (effective-address-extra second-operand modifier))))))
219 '(("BCHG" . #b01) ("BCLR" . #b10) ("BSET" . #b11) ))
220 ;; Note that BTST supports PC-relative, while the above three do
221 ;; not.
222 ("BTST"
223 (((byte long) (data-register) (data-addressing-modes))
224 ((4 #b0000) (3 (register-idx first-operand))
225 (3 #b100)
226 (6 (effective-address-mode second-operand modifier))
227 (? (effective-address-extra second-operand modifier))))
228 (((byte long) (immediate) (data-addressing-modes))
229 ((10 #b0000100000)
230 (6 (effective-address-mode second-operand modifier))
231 (8 #b00000000) (8 (immediate-value first-operand 'byte))
232 (? (effective-address-extra second-operand modifier)))))
234 ("CHK"
235 (((word) (data-addressing-modes) (data-register))
236 ((4 #b0100) (3 (register-idx second-operand)) (3 #b110)
237 (6 (effective-address-mode first-operand modifier))
238 (? (effective-address-extra first-operand modifier)))))
240 ,@(mapcar
241 (lambda (x y)
242 `(,x
243 (((byte word long) (data-alterable-modes))
244 ((5 #b01000)
245 (3 ,y)
246 (2 (modifier-bits modifier))
247 (6 (effective-address-mode first-operand modifier))
248 (? (effective-address-extra first-operand modifier))))))
249 '("CLR" "NEG" "NEGX" "NOT")
250 '(#b010 #b100 #b000 #b110))
252 ("CMP"
253 "CMPI" ; I is faster
254 (((byte word long) (all-ea-modes) (data-register))
255 ((4 #b1011) (3 (register-idx second-operand)) (1 #b0)
256 (2 (modifier-bits modifier))
257 (6 (effective-address-mode first-operand modifier))
258 (? (effective-address-extra first-operand modifier))))
259 "CMPA" "CMPM")
260 ("CMPA"
261 (((word long) (all-ea-modes) (address-register))
262 ((4 #b1011) (3 (register-idx second-operand))
263 (3 (if-eql-word-p modifier #b011 #b111))
264 (6 (effective-address-mode first-operand modifier))
265 (? (effective-address-extra first-operand modifier)))))
266 ("CMPI"
267 (((byte word long) (immediate) (data-alterable-modes))
268 ((8 #b00001100) (2 (modifier-bits modifier))
269 (6 (effective-address-mode second-operand modifier))
270 (? (immediate-value first-operand modifier))
271 (? (effective-address-extra second-operand modifier)))))
272 ("CMPM"
273 (((byte word long) (postincrement-indirect) (postincrement-indirect))
274 ((4 #b1011) (3 (register-idx second-operand))
275 (1 #b1) (2 (modifier-bits modifier)) (3 #b001)
276 (3 (register-idx first-operand)))))
278 ,@(mapcar
279 (lambda (x)
280 `(,(car x)
281 (((word) (data-register) (absolute))
282 ((4 #b0101) (4 ,(cdr x)) (5 #b11001)
283 (3 (register-idx first-operand))
284 (16 (branch-displacement-bits second-operand modifier
285 :db-p t))))))
286 '(("DBCC" . #b0100) ("DBCS" . #b0101) ("DBEQ" . #b0111)
287 ("DBGE" . #b1100) ("DBGT" . #b1110) ("DBHI" . #b0010)
288 ("DBLE" . #b1111) ("DBLS" . #b0011) ("DBLT" . #b1101)
289 ("DBMI" . #b1011) ("DBNE" . #b0110) ("DBPL" . #b1010)
290 ("DBVC" . #b1000) ("DBVS" . #b1001) ("DBT" . #b0000)
291 ("DBRA" . #b0000) ("DBF" . #b0001)))
293 ,@(mapcar
294 (lambda (x)
295 `(,x
296 (((word) (data-addressing-modes) (data-register))
297 ((4 ,(if (or (string= x "DIVS") (string= x "DIVU"))
298 #b1000 #b1100))
299 (3 (register-idx second-operand))
300 (3 ,(if (or (string= x "DIVS") (string= x "MULS"))
301 #b111 #b011))
302 (6 (effective-address-mode first-operand modifier))
303 (? (effective-address-extra first-operand modifier))))))
304 '("DIVS" "DIVU" "MULS" "MULU"))
306 ("EXG"
307 (((long) (data-register) (data-register))
308 ((4 #b1100) (3 (register-idx first-operand))
309 (6 #b101000) (3 (register-idx second-operand))))
310 (((long) (address-register) (address-register))
311 ((4 #b1100) (3 (register-idx first-operand))
312 (6 #b101001) (3 (register-idx second-operand))))
313 (((long) (data-register) (address-register))
314 ((4 #b1100) (3 (register-idx first-operand))
315 (6 #b110001) (3 (register-idx second-operand)))))
317 ("EXT"
318 (((word long) (data-register))
319 ((7 #b0100100) (3 (if-eql-word-p modifier #b010 #b011))
320 (3 #b000) (3 (register-idx first-operand)))))
322 ("ILLEGAL" (nil ((16 #b0100101011111100))))
324 ("JMP"
325 ((nil (control-addressing-modes))
326 ((10 #b0100111011) (6 (effective-address-mode first-operand modifier))
327 (? (effective-address-extra first-operand modifier)))))
328 ("JSR"
329 ((nil (control-addressing-modes))
330 ((10 #b0100111010) (6 (effective-address-mode first-operand modifier))
331 (? (effective-address-extra first-operand modifier)))))
333 ("LEA"
334 (((long) (control-addressing-modes) (address-register))
335 ((4 #b0100) (3 (register-idx second-operand)) (3 #b111)
336 (6 (effective-address-mode first-operand modifier))
337 (? (effective-address-extra first-operand modifier)))))
339 ("LINK"
340 ((nil (address-register) (immediate))
341 ((13 #b0100111001010) (3 (register-idx first-operand))
342 (16 (immediate-value second-operand)))))
344 ("MOVE"
345 (((byte word long) (all-ea-modes) (data-alterable-modes))
346 ((2 #b00) (2 (modifier-bits-for-move modifier))
347 (6 (effective-address-mode second-operand modifier :flipped-p t))
348 (6 (effective-address-mode first-operand modifier))
349 (? (effective-address-extra first-operand modifier))
350 (? (effective-address-extra second-operand modifier))))
351 (((word) (register (string-equal value "CCR"))
352 (data-alterable-modes))
353 ((10 #b0100001011) (6 (effective-address-mode second-operand modifier))
354 (? (effective-address-extra second-operand modifier))))
355 (((word) (data-addressing-modes) (register (string-equal value "CCR")))
356 ((10 #b0100010011) (6 (effective-address-mode first-operand modifier))
357 (? (effective-address-extra first-operand modifier))))
358 (((word) (data-addressing-modes) (register (string-equal value "SR")))
359 ((10 #b0100011011) (6 (effective-address-mode first-operand modifier))
360 (? (effective-address-extra first-operand modifier))))
361 (((word) (register (string-equal value "SR")) (data-alterable-modes))
362 ((10 #b0100000011) (6 (effective-address-mode second-operand modifier))
363 (? (effective-address-extra second-operand modifier))))
364 (((long) (register (string-equal value "USP")) (address-register))
365 ((13 #b0100111001101) (3 (register-idx second-operand))))
366 (((long) (register (string-equal value "USP")) (address-register))
367 ((13 #b0100111001101) (3 (register-idx second-operand))))
368 "MOVEA" "MOVEQ")
369 ("MOVEA"
370 (((word long) (all-ea-modes) (address-register))
371 ((2 #b00) (2 (modifier-bits-for-move modifier))
372 (3 (register-idx second-operand)) (3 #b001)
373 (6 (effective-address-mode first-operand modifier))
374 (? (effective-address-extra first-operand modifier)))))
375 ;; ("MOVEC") ;; XXX I don't understand the syntax for this one.
376 ("MOVEM"
377 (((word long) (register-list) (movem-pre-modes))
378 ((9 #b010010001) (1 (if-eql-word-p modifier 0 1))
379 (6 (effective-address-mode second-operand modifier))
380 (16 (register-mask-list first-operand second-operand))
381 (? (effective-address-extra second-operand modifier))))
382 (((word long) (movem-post-modes) (register-list))
383 ((9 #b010011001) (1 (if-eql-word-p modifier 0 1))
384 (6 (effective-address-mode first-operand modifier))
385 (16 (register-mask-list second-operand))
386 (? (effective-address-extra first-operand modifier)))))
387 ("MOVEP"
388 (((word long) (data-register) (displacement-indirect))
389 ((4 #b0000) (3 (register-idx first-operand))
390 (3 (if-eql-word-p modifier #b110 #b111)) (3 #b001)
391 (3 (register-idx (indirect-base-register second-operand)))))
392 (((word long) (displacement-indirect) (data-register))
393 ((4 #b0000) (3 (register-idx second-operand))
394 (3 (if-eql-word-p modifier #b100 #b101)) (3 #b001)
395 (3 (register-idx (indirect-base-register first-operand))))))
396 ("MOVEQ"
397 (((long) (immediate (<= 0 value 255)) (data-register))
398 ((4 #b0111) (3 (register-idx second-operand)) (1 #b0)
399 (8 (immediate-value first-operand)))))
400 ;; XXX MOVES (68010 instruction)
402 ("NBCD"
403 (((byte) (data-alterable-modes))
404 ((10 #b0100100000) (6 (effective-address-mode first-operand modifier))
405 (? (effective-address-extra first-operand modifier)))))
407 ("RESET" (nil ((16 #b0100111001110000))))
408 ("NOP" (nil ((16 #b0100111001110001))))
409 ("STOP" (nil ((16 #b0100111001110010))))
410 ("RTE" (nil ((16 #b0100111001110011))))
411 ("RTD" (nil ((16 #b0100111001110100))))
412 ("RTS" (nil ((16 #b0100111001110101))))
413 ("TRAPV" (nil ((16 #b0100111001110110))))
414 ("RTR" (nil ((16 #b0100111001110111))))
416 ("PEA"
417 (((long) (control-addressing-modes))
418 ((10 #b0100100001) (6 (effective-address-mode first-operand modifier))
419 (? (effective-address-extra first-operand modifier)))))
421 ,@(mapcar
422 (lambda (x)
423 `(,(car x)
424 (((byte) (data-alterable-modes))
425 ((4 #b0101) (4 ,(cdr x)) (2 #b11)
426 (6 (effective-mode-mode first-operand))
427 (? (effective-mode-extra first-operand))))))
428 '(("SCC" . #b0100) ("SCS" . #b0101) ("SEQ" . #b0111) ("SGE" . #b1100)
429 ("SGT" . #b1110) ("SHI" . #b0010) ("SLE" . #b1111) ("SLS" . #b0011)
430 ("SLT" . #b1101) ("SMI" . #b1011) ("SNE" . #b0110) ("SPL" . #b1010)
431 ("SVC" . #b1000) ("SVS" . #b1001) ("ST" . #b0000) ("SF" . #b0001)))
433 ("SWAP"
434 (((word) (data-register))
435 ((13 #b0100100001000) (3 (register-idx first-operand)))))
437 ("TAS"
438 (((byte) (data-alterable-modes))
439 ((10 #b0100101011) (6 (effective-address-mode first-operand modifier))
440 (? (effective-address-extra first-operand modifier)))))
442 ("TRAP"
443 ((nil (immediate (<= 0 value 15)))
444 ((12 #b010011100100) (4 (immediate-value first-operand)))))
446 ("TST"
447 (((byte word long) (data-alterable-modes))
448 ((8 #b01001010) (2 (modifier-bits modifier))
449 (6 (effective-address-mode first-operand modifier))
450 (? (effective-address-extra first-operand modifier)))))
452 ("UNLK"
453 ((nil (address-register))
454 ((13 #b0100111001011) (3 (register-idx first-operand)))))))
457 ;; The order of elements in this table are significant.
458 (defparameter *asm-register-table*
459 #(("d0") ("d1") ("d2") ("d3") ("d4") ("d5") ("d6") ("d7")
460 ("a0") ("a1") ("a2") ("a3") ("a4") ("a5") ("a6") ("a7")
461 ("pc") ("ccr") ("sr") ("ssp") ("usp")))
464 ;;;; HELPER FUNCTIONS
466 (defun register-substitutions (string)
467 ;; XXX: allow dynamic register substitutions for EQUR directive
468 (when (string-equal string "sp") (setf string "a7"))
469 string)
471 (defun register-p (string)
472 (find string *asm-register-table* :key #'car :test #'string-equal))
474 (defun opcode-p (string)
475 (get-asm-opcode string))
477 (defun get-asm-opcode (string)
478 (find string *asm-opcode-table* :key #'car :test #'string-equal))
480 ;; PSEUDO-OP-P has been moved to assembler.lisp
482 ;;; Really dumb, but this was the only thing in the code generation
483 ;;; table that needed to be changed to a function call in order to
484 ;;; stop using eval in the code generator.
485 (defun if-eql-word-p (modifier a b)
486 (if (eql modifier 'word) a b))
488 (defun modifier-size-in-bits (modifier)
489 (ecase modifier (byte 8) (word 16) (long 32)))