1 ;;; Tables and things which are truly machine (m68k) specific.
3 ;;; Julian Squires/2005
5 (in-package :m68k-assembler
)
7 (defparameter *asm-opcode-table
*
8 ;; first field is the opcode name, sans modifiers. remaining fields
9 ;; are either pairs of operand constraints and code generation
10 ;; masks, or functions. these are matched or called in sequence,
11 ;; until one can be found which matches.
13 ;; Code generation masks are lists in the form: (size code) where
14 ;; size indicates the number of bits this part should take up, and
15 ;; code is the code to evaluate when generating this part of the
16 ;; expression. (Actually, code should be a function call, now.)
17 ;; The list starts from the most significant bit of the instruction
18 ;; word and moves down. SIZE fields of ? indicate a variable size,
19 ;; where the code in question will return a suitable size value as a
24 (((byte) (data-register) (data-register)) .
25 ((4 ,(if (string= x
"ABCD") #b1101
#b1001
))
26 (3 (register-idx second-operand
)) (6 #b100000
)
27 (3 (register-idx first-operand
))))
28 (((byte) (predecrement-indirect) (predecrement-indirect))
29 ((4 ,(if (string= x
"ABCD") #b1101
#b1001
))
30 (3 (register-idx second-operand
)) (6 #b100001
)
31 (3 (register-idx first-operand
))))))
37 (((byte word long
) (all-ea-modes) (data-register))
38 ((4 ,(if (string= x
"ADD") #b1101
#b1001
))
39 (3 (register-idx second-operand
)) (1 #b0
)
40 (2 (modifier-bits modifier
))
41 (6 (effective-address-mode first-operand modifier
))
42 (?
(effective-address-extra first-operand modifier
))))
43 (((byte word long
) (data-register) (memory-alterable-modes))
44 ((4 ,(if (string= x
"ADD") #b1101
#b1001
))
45 (3 (register-idx first-operand
)) (1 #b1
)
46 (2 (modifier-bits modifier
))
47 (6 (effective-address-mode second-operand modifier
))
48 (?
(effective-address-extra second-operand modifier
))))
49 ,(concatenate 'string x
"A")
50 ,(concatenate 'string x
"I")
51 ,(concatenate 'string x
"Q")
52 ,(concatenate 'string x
"X"))
53 (,(concatenate 'string x
"A")
54 (((word long
) (all-ea-modes) (address-register))
55 ((4 ,(if (string= x
"ADD") #b1101
#b1001
))
56 (3 (register-idx second-operand
))
57 (3 (if-eql-word-p modifier
#b011
#b111
))
58 (6 (effective-address-mode first-operand modifier
))
59 (?
(effective-address-extra first-operand modifier
)))))
60 (,(concatenate 'string x
"I")
61 (((byte word long
) (immediate) (data-alterable-modes))
62 ((8 ,(if (string= x
"ADD") #b00000110
#b00000100
))
63 (2 (modifier-bits modifier
))
64 (6 (effective-address-mode second-operand modifier
))
65 (?
(immediate-value first-operand modifier
))
66 (?
(effective-address-extra second-operand modifier
)))))
67 (,(concatenate 'string x
"Q")
68 (((byte word long
) (immediate (<= 1 value
8)) (alterable-modes))
69 ((4 #b0101
) (3 (addq-immediate-value first-operand
))
70 (1 ,(if (string= x
"ADD") 0 1))
71 (2 (modifier-bits modifier
))
72 (6 (effective-address-mode second-operand modifier
))
73 (?
(effective-address-extra second-operand modifier
)))))
74 (,(concatenate 'string x
"X")
75 (((byte word long
) (data-register) (data-register))
76 ((4 ,(if (string= x
"ADD") #b1101
#b1001
))
77 (3 (register-idx second-operand
)) (1 #b1
)
78 (2 (modifier-bits modifier
))
79 (3 #b000
) (3 (register-idx first-operand
))))
80 (((byte word long
) (predecrement-indirect) (predecrement-indirect))
81 ((4 #b1101
) (3 (register-idx second-operand
)) (1 #b1
)
82 (2 (modifier-bits modifier
))
83 (3 #b001
) (3 (register-idx first-operand
)))))))
89 ,@(unless (string= x
"EOR")
90 `((((byte word long
) (data-addressing-modes) (data-register))
91 ((4 ,(cond ((string= x
"AND") #b1100
)
92 ((string= x
"OR") #b1000
)))
93 (3 (register-idx second-operand
)) (1 #b0
)
94 (2 (modifier-bits modifier
))
95 (6 (effective-address-mode first-operand modifier
))
96 (?
(effective-address-extra first-operand modifier
))))))
97 (((byte word long
) (data-register) (memory-alterable-modes))
98 ((4 ,(cond ((string= x
"AND") #b1100
)
99 ((string= x
"EOR") #b1011
)
100 ((string= x
"OR") #b1000
)))
101 (3 (register-idx first-operand
)) (1 #b1
)
102 (2 (modifier-bits modifier
))
103 (6 (effective-address-mode second-operand modifier
))
104 (?
(effective-address-extra second-operand modifier
))))
105 ,(concatenate 'string x
"I"))
106 (,(concatenate 'string x
"I")
107 (((byte word long
) (immediate) (data-alterable-modes))
109 (4 ,(cond ((string= x
"AND") #b0010
)
110 ((string= x
"EOR") #b1010
)
111 ((string= x
"OR") #b0000
)))
112 (2 (modifier-bits modifier
))
113 (6 (effective-address-mode second-operand modifier
))
114 (?
(immediate-value first-operand modifier
))
115 (?
(effective-address-extra second-operand modifier
))))
116 (((byte) (immediate) (register (string-equal value
"CCR")))
118 (4 ,(cond ((string= x
"AND") #b0010
)
119 ((string= x
"EOR") #b1010
)
120 ((string= x
"OR") #b0000
)))
121 (16 #b0011110000000000
)
122 (8 (immediate-value first-operand
'byte
))))
123 (((word) (immediate) (register (string-equal value
"SR")))
125 (4 ,(cond ((string= x
"AND") #b0010
)
126 ((string= x
"EOR") #b1010
)
127 ((string= x
"OR") #b0000
)))
129 (16 (immediate-value first-operand
'word
)))))))
135 (((byte word long
) (data-register) (data-register))
136 ((4 #b1110
) (3 (register-idx first-operand
))
137 (1 ,(if (string= x
"L" :start1
(1- (length x
))) 1 0))
138 (2 (modifier-bits modifier
))
139 (3 ,(cond ((string= x
"LS" :end1
2) #b001
)
140 ((string= x
"AS" :end1
2) #b000
)
141 ((string= x
"ROX" :end1
3) #b010
)
143 (3 (register-idx second-operand
))))
144 (((byte word long
) (immediate (<= 1 value
8)) (data-register))
145 ((4 #b1110
) (3 (immediate-value first-operand
))
146 (1 ,(if (string= x
"L" :start1
(1- (length x
))) 1 0))
147 (2 (modifier-bits modifier
))
148 (3 ,(cond ((string= x
"LS" :end1
2) #b101
)
149 ((string= x
"AS" :end1
2) #b100
)
150 ((string= x
"ROX" :end1
3) #b110
)
152 (3 (register-idx second-operand
))))
153 (((byte word long
) (memory-alterable-modes))
155 (2 ,(cond ((string= x
"LS" :end1
2) #b01
)
156 ((string= x
"AS" :end1
2) #b00
)
157 ((string= x
"ROX" :end1
3) #b10
)
159 (1 ,(if (string= x
"L" :start1
(1- (length x
))) 1 0))
160 (2 #b11
) (6 (effective-address-mode first-operand modifier
))
161 (?
(effective-address-extra first-operand modifier
))))))
162 '("ASL" "ASR" "LSL" "LSR" "ROL" "ROR" "ROXL" "ROXR"))
167 (((byte word
) (absolute))
168 ((4 #b0110
) (4 ,(cdr x
))
169 (?
(branch-displacement-bits first-operand modifier
))))))
170 '(("BCC" .
#b0100
) ("BCS" .
#b0101
) ("BEQ" .
#b0111
) ("BGE" .
#b1100
)
171 ("BGT" .
#b1110
) ("BHI" .
#b0010
) ("BLE" .
#b1111
) ("BLS" .
#b0011
)
172 ("BLT" .
#b1101
) ("BMI" .
#b1011
) ("BNE" .
#b0110
) ("BPL" .
#b1010
)
173 ("BVC" .
#b1000
) ("BVS" .
#b1001
) ("BRA" .
#b0000
) ("BSR" .
#b0001
)))
178 (((byte long
) (data-register) (data-alterable-modes))
179 ((4 #b0000
) (3 (register-idx first-operand
))
181 (6 (effective-address-mode second-operand modifier
))
182 (?
(effective-address-extra second-operand modifier
))))
183 (((byte long
) (immediate) (data-alterable-modes))
184 ((8 #b00001000
) (2 ,(cdr x
))
185 (6 (effective-address-mode second-operand modifier
))
186 (8 #b00000000
) (8 (immediate-value immediate
'byte
))
187 (?
(effective-address-extra second-operand modifier
))))))
188 '(("BCHG" .
#b01
) ("BCLR" .
#b10
) ("BSET" .
#b11
) ))
189 ;; Note that BTST supports PC-relative, while the above three do
192 (((byte long
) (data-register) (data-addressing-modes))
193 ((4 #b0000
) (3 (register-idx first-operand
))
195 (6 (effective-address-mode second-operand modifier
))
196 (?
(effective-address-extra second-operand modifier
))))
197 (((byte long
) (immediate) (data-addressing-modes))
199 (6 (effective-address-mode second-operand modifier
))
200 (8 #b00000000
) (8 (immediate-value immediate
'byte
))
201 (?
(effective-address-extra second-operand modifier
)))))
204 (((word) (data-addressing-modes) (data-register))
205 ((4 #b0100
) (3 (register-idx second-operand
)) (3 #b110
)
206 (6 (effective-address-mode first-operand modifier
))
207 (?
(effective-address-extra first-operand modifier
)))))
212 (((byte word long
) (data-alterable-modes))
214 (3 ,(cond ((string= x
"NOT") #b110
)
215 ((string= x
"NEG") #b100
)
216 ((string= x
"NEGX") #b000
)
217 ((string= x
"CLR") #b010
)))
218 (2 (modifier-bits modifier
))
219 (6 (effective-address-mode first-operand modifier
))
220 (?
(effective-address-extra first-operand modifier
))))))
221 '("CLR" "NEG" "NEGX" "NOT"))
224 (((byte word long
) (all-ea-modes) (data-register))
225 ((4 #b1011
) (3 (register-idx second-operand
)) (1 #b0
)
226 (2 (modifier-bits modifier
))
227 (6 (effective-address-mode first-operand modifier
))
228 (?
(effective-address-extra first-operand modifier
))))
229 "CMPA" "CMPI" "CMPM")
231 (((word long
) (all-ea-modes) (address-register))
232 ((4 #b1011
) (3 (register-idx second-operand
))
233 (3 (if-eql-word-p modifier
#b011
#b111
))
234 (6 (effective-address-mode first-operand modifier
))
235 (?
(effective-address-extra first-operand modifier
)))))
237 (((byte word long
) (immediate) (data-alterable-modes))
238 ((8 #b00001100
) (2 (modifier-bits modifier
))
239 (6 (effective-address-mode second-operand modifier
))
240 (?
(immediate-value first-operand modifier
))
241 (?
(effective-address-extra second-operand modifier
)))))
243 (((byte word long
) (postincrement-indirect) (postincrement-indirect))
244 ((4 #b1011
) (3 (register-idx second-operand
))
245 (1 #b1
) (2 (modifier-bits modifier
)) (3 #b001
)
246 (3 (register-idx first-operand
)))))
251 (((word) (data-register) (absolute))
252 ((4 #b0101
) (4 ,(cdr x
)) (5 #b11001
)
253 (3 (register-idx first-operand
))
254 (16 (branch-displacement-bits second-operand modifier
256 '(("DBCC" .
#b0100
) ("DBCS" .
#b0101
) ("DBEQ" .
#b0111
)
257 ("DBGE" .
#b1100
) ("DBGT" .
#b1110
) ("DBHI" .
#b0010
)
258 ("DBLE" .
#b1111
) ("DBLS" .
#b0011
) ("DBLT" .
#b1101
)
259 ("DBMI" .
#b1011
) ("DBNE" .
#b0110
) ("DBPL" .
#b1010
)
260 ("DBVC" .
#b1000
) ("DBVS" .
#b1001
) ("DBT" .
#b0000
)
261 ("DBRA" .
#b0000
) ("DBF" .
#b0001
)))
266 (((word) (data-addressing-modes) (data-register))
267 ((4 ,(if (or (string= x
"DIVS") (string= x
"DIVU"))
269 (3 (register-idx second-operand
))
270 (3 ,(if (or (string= x
"DIVS") (string= x
"MULS"))
272 (6 (effective-address-mode first-operand modifier
))
273 (?
(effective-address-extra first-operand modifier
))))))
274 '("DIVS" "DIVU" "MULS" "MULU"))
277 (((long) (data-register) (data-register))
278 ((4 #b1100
) (3 (register-idx first-operand
))
279 (6 #b101000
) (3 (register-idx second-operand
))))
280 (((long) (address-register) (address-register))
281 ((4 #b1100
) (3 (register-idx first-operand
))
282 (6 #b101001
) (3 (register-idx second-operand
))))
283 (((long) (data-register) (address-register))
284 ((4 #b1100
) (3 (register-idx first-operand
))
285 (6 #b110001
) (3 (register-idx second-operand
)))))
288 (((word long
) (data-register))
289 ((7 #b0100100
) (3 (if-eql-word-p modifier
#b010
#b011
))
290 (3 #b000
) (3 (register-idx first-operand
)))))
292 ("ILLEGAL" (nil ((16 #b0100101011111100
))))
295 ((nil (control-addressing-modes))
296 ((10 #b0100111011
) (6 (effective-address-mode first-operand modifier
))
297 (?
(effective-address-extra first-operand modifier
)))))
299 ((nil (control-addressing-modes))
300 ((10 #b0100111010
) (6 (effective-address-mode first-operand modifier
))
301 (?
(effective-address-extra first-operand modifier
)))))
304 (((long) (control-addressing-modes) (address-register))
305 ((4 #b0100
) (3 (register-idx second-operand
)) (3 #b111
)
306 (6 (effective-address-mode first-operand modifier
))
307 (?
(effective-address-extra first-operand modifier
)))))
310 ((nil (address-register) (immediate))
311 ((13 #b0100111001010
) (3 (register-idx first-operand
))
312 (16 (immediate-value immediate
)))))
315 (((byte word long
) (all-ea-modes) (data-alterable-modes))
316 ((2 #b00
) (2 (modifier-bits-for-move modifier
))
317 (6 (effective-address-mode second-operand modifier
:flipped-p t
))
318 (6 (effective-address-mode first-operand modifier
))
319 (?
(effective-address-extra first-operand modifier
))
320 (?
(effective-address-extra second-operand modifier
))))
321 (((word) (register (string-equal value
"CCR"))
322 (data-alterable-modes))
323 ((10 #b0100001011
) (6 (effective-address-mode second-operand modifier
))
324 (?
(effective-address-extra second-operand modifier
))))
325 (((word) (data-addressing-modes) (register (string-equal value
"CCR")))
326 ((10 #b0100010011
) (6 (effective-address-mode first-operand modifier
))
327 (?
(effective-address-extra first-operand modifier
))))
328 (((word) (data-addressing-modes) (register (string-equal value
"SR")))
329 ((10 #b0100011011
) (6 (effective-address-mode first-operand modifier
))
330 (?
(effective-address-extra first-operand modifier
))))
331 (((word) (register (string-equal value
"SR")) (data-alterable-modes))
332 ((10 #b0100000011
) (6 (effective-address-mode second-operand modifier
))
333 (?
(effective-address-extra second-operand modifier
))))
334 (((long) (register (string-equal value
"USP")) (address-register))
335 ((13 #b0100111001101
) (3 (register-idx second-operand
))))
336 (((long) (register (string-equal value
"USP")) (address-register))
337 ((13 #b0100111001101
) (3 (register-idx second-operand
))))
340 (((word long
) (all-ea-modes) (address-register))
341 ((2 #b00
) (2 (modifier-bits-for-move modifier
))
342 (3 (register-idx second-operand
)) (3 #b001
)
343 (6 (effective-address-mode first-operand modifier
))
344 (?
(effective-address-extra first-operand modifier
)))))
345 ("MOVEC") ;; XXX I don't understand the syntax for this one.
347 (((word long
) (register-list) (movem-pre-modes))
348 ((9 #b010010001
) (1 (if-eql-word-p modifier
0 1))
349 (6 (effective-address-mode second-operand modifier
))
350 (16 (register-mask-list first-operand
:flipped-p t
))
351 (?
(effective-address-extra second-operand modifier
))))
352 (((word long
) (movem-post-modes) (register-list))
353 ((9 #b010011001
) (1 (if-eql-word-p modifier
0 1))
354 (6 (effective-address-mode first-operand modifier
))
355 (16 (register-mask-list second-operand
:flipped-p nil
))
356 (?
(effective-address-extra first-operand modifier
)))))
358 (((word long
) (data-register) (displacement-indirect))
359 ((4 #b0000
) (3 (register-idx first-operand
))
360 (3 (if-eql-word-p modifier
#b110
#b111
)) (3 #b001
)
361 (3 (register-idx (indirect-base-register second-operand
)))))
362 (((word long
) (displacement-indirect) (data-register))
363 ((4 #b0000
) (3 (register-idx second-operand
))
364 (3 (if-eql-word-p modifier
#b100
#b101
)) (3 #b001
)
365 (3 (register-idx (indirect-base-register first-operand
))))))
367 (((long) (immediate (<= 0 value
255)) (data-register))
368 ((4 #b0111
) (3 (register-idx second-operand
)) (1 #b0
)
369 (8 (immediate-value first-operand
)))))
370 ;; XXX MOVES (68010 instruction)
373 (((byte) (data-alterable-modes))
374 ((10 #b0100100000
) (6 (effective-address-mode first-operand modifier
))
375 (?
(effective-address-extra first-operand modifier
)))))
377 ("RESET" (nil ((16 #b0100111001110000
))))
378 ("NOP" (nil ((16 #b0100111001110001
))))
379 ("STOP" (nil ((16 #b0100111001110010
))))
380 ("RTE" (nil ((16 #b0100111001110011
))))
381 ("RTD" (nil ((16 #b0100111001110100
))))
382 ("RTS" (nil ((16 #b0100111001110101
))))
383 ("TRAPV" (nil ((16 #b0100111001110110
))))
384 ("RTR" (nil ((16 #b0100111001110111
))))
387 (((long) (control-addressing-modes))
388 ((10 #b0100100001
) (6 (effective-address-mode first-operand modifier
))
389 (?
(effective-address-extra first-operand modifier
)))))
394 (((byte) (data-alterable-modes))
395 ((4 #b0101
) (4 ,(cdr x
)) (2 #b11
)
396 (6 (effective-mode-mode first-operand
))
397 (?
(effective-mode-extra first-operand
))))))
398 '(("SCC" .
#b0100
) ("SCS" .
#b0101
) ("SEQ" .
#b0111
) ("SGE" .
#b1100
)
399 ("SGT" .
#b1110
) ("SHI" .
#b0010
) ("SLE" .
#b1111
) ("SLS" .
#b0011
)
400 ("SLT" .
#b1101
) ("SMI" .
#b1011
) ("SNE" .
#b0110
) ("SPL" .
#b1010
)
401 ("SVC" .
#b1000
) ("SVS" .
#b1001
) ("ST" .
#b0000
) ("SF" .
#b0001
)))
404 (((word) (data-register))
405 ((13 #b0100100001000
) (3 (register-idx first-operand
)))))
408 (((byte) (data-alterable-modes))
409 ((10 #b0100101011
) (6 (effective-address-mode first-operand modifier
))
410 (?
(effective-address-extra first-operand modifier
)))))
413 ((nil (immediate (<= 0 value
15)))
414 ((12 #b010011100100
) (4 (immediate-value first-operand
)))))
417 (((byte word long
) (data-alterable-modes))
418 ((8 #b01001010
) (2 (modifier-bits modifier
))
419 (6 (effective-address-mode first-operand modifier
))
420 (?
(effective-address-extra first-operand modifier
)))))
423 ((nil (address-register))
424 ((13 #b0100111001011
) (3 (register-idx first-operand
)))))))
427 ;; The order of elements in this table are significant.
428 (defparameter *asm-register-table
*
429 #(("d0") ("d1") ("d2") ("d3") ("d4") ("d5") ("d6") ("d7")
430 ("a0") ("a1") ("a2") ("a3") ("a4") ("a5") ("a6") ("a7")
431 ("pc") ("ccr") ("sr") ("ssp") ("usp")))
434 ;;;; HELPER FUNCTIONS
436 (defun munge-modifier (string)
437 (let ((modifier nil
))
438 (awhen (position #\. string
)
439 (setf modifier
(subseq string
(1+ it
)))
440 (setf string
(subseq string
0 it
)))
441 (values string modifier
)))
443 (defun register-substitutions (string)
444 ;; XXX: allow dynamic register substitutions for EQUR directive
445 (when (string-equal string
"sp") (setf string
"a7"))
448 (defun register-p (string)
449 (find string
*asm-register-table
* :key
#'car
:test
#'string-equal
))
451 (defun opcode-p (string)
452 (find string
*asm-opcode-table
* :key
#'car
:test
#'string-equal
))
454 ;; PSEUDO-OP-P has been moved to assembler.lisp
456 ;;; Really dumb, but this was the only thing in the code generation
457 ;;; table that needed to be changed to a function call in order to
458 ;;; stop using eval in the code generator.
459 (defun if-eql-word-p (modifier a b
)
460 (if (eql modifier
'word
) a b
))