1 ;;; Tables and things which are truly machine (m68k) specific.
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
)
13 ,(set-difference all-ea-modes
14 '(immediate pc-index pc-displacement
)))
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
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
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
))))))
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
)))))))
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))
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")))
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")))
156 (4 ,(cond ((string= x
"AND") #b0010
)
157 ((string= x
"EOR") #b1010
)
158 ((string= x
"OR") #b0000
)))
160 (16 (immediate-value first-operand
'word
)))))))
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
)
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
)
183 (3 (register-idx second-operand
))))
184 (((byte word long
) (memory-alterable-modes))
186 (2 ,(cond ((string= x
"LS" :end1
2) #b01
)
187 ((string= x
"AS" :end1
2) #b00
)
188 ((string= x
"ROX" :end1
3) #b10
)
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"))
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
)))
209 (((byte long
) (data-register) (data-alterable-modes))
210 ((4 #b0000
) (3 (register-idx first-operand
))
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
223 (((byte long
) (data-register) (data-addressing-modes))
224 ((4 #b0000
) (3 (register-idx first-operand
))
226 (6 (effective-address-mode second-operand modifier
))
227 (?
(effective-address-extra second-operand modifier
))))
228 (((byte long
) (immediate) (data-addressing-modes))
230 (6 (effective-address-mode second-operand modifier
))
231 (8 #b00000000
) (8 (immediate-value first-operand
'byte
))
232 (?
(effective-address-extra second-operand modifier
)))))
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
)))))
243 (((byte word long
) (data-alterable-modes))
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
))
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
))))
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
)))))
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
)))))
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
)))))
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
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
)))
296 (((word) (data-addressing-modes) (data-register))
297 ((4 ,(if (or (string= x
"DIVS") (string= x
"DIVU"))
299 (3 (register-idx second-operand
))
300 (3 ,(if (or (string= x
"DIVS") (string= x
"MULS"))
302 (6 (effective-address-mode first-operand modifier
))
303 (?
(effective-address-extra first-operand modifier
))))))
304 '("DIVS" "DIVU" "MULS" "MULU"))
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
)))))
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
))))
325 ((nil (control-addressing-modes))
326 ((10 #b0100111011
) (6 (effective-address-mode first-operand modifier
))
327 (?
(effective-address-extra first-operand modifier
)))))
329 ((nil (control-addressing-modes))
330 ((10 #b0100111010
) (6 (effective-address-mode first-operand modifier
))
331 (?
(effective-address-extra first-operand modifier
)))))
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
)))))
340 ((nil (address-register) (immediate))
341 ((13 #b0100111001010
) (3 (register-idx first-operand
))
342 (16 (immediate-value second-operand
)))))
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
))))
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.
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
)))))
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
))))))
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)
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
))))
417 (((long) (control-addressing-modes))
418 ((10 #b0100100001
) (6 (effective-address-mode first-operand modifier
))
419 (?
(effective-address-extra first-operand modifier
)))))
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
)))
434 (((word) (data-register))
435 ((13 #b0100100001000
) (3 (register-idx first-operand
)))))
438 (((byte) (data-alterable-modes))
439 ((10 #b0100101011
) (6 (effective-address-mode first-operand modifier
))
440 (?
(effective-address-extra first-operand modifier
)))))
443 ((nil (immediate (<= 0 value
15)))
444 ((12 #b010011100100
) (4 (immediate-value first-operand
)))))
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
)))))
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"))
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)))