1 ;;;;------------------------------------------------------------------
3 ;;;; Copyright (C) 20012000, 2002-2005,
4 ;;;; Department of Computer Science, University of Tromso, Norway
6 ;;;; Filename: operands.lisp
7 ;;;; Description: Operand representation.
8 ;;;; Author: Frode Vatvedt Fjeld <frodef@acm.org>
9 ;;;; Created at: Wed Feb 16 14:02:57 2000
10 ;;;; Distribution: See the accompanying file COPYING.
12 ;;;; $Id: operands.lisp,v 1.6 2005/08/13 20:31:51 ffjeld Exp $
14 ;;;;------------------------------------------------------------------
18 ;;; ----------------------------------------------------------------
20 ;;; ----------------------------------------------------------------
22 ;;; Operand types are identified by symbols
24 (defmacro def-operand-types
(&rest ot-specs
)
25 (list* 'cl
:eval-when
'(:load-toplevel
)
26 (loop for
(sym . properties
) in ot-specs
28 `((setf ,@(loop for
(p v
) in properties
29 appending
`((cl:get
',sym
',p
) ,v
)))
30 (import ',sym
:ia-x86-instr
)))))
32 (defun operand-type-property (sym p
)
36 (immediate (immediate t
))
37 (displacement (immediate nil
))
56 (imm16-8 (immediate t
)
66 (m (bit-size 32)) ; memory poiner
68 (mm (bit-size 64)) ; mmx register
69 (mm/m64
(immediate nil
))
70 (mm/m32
(immediate nil
))
71 (xmm (bit-size 128)) ; simd register
72 (xmm/m128
) (xmm/m64
) (xmm/m32
)
73 (moffs8 (immediate nil
)
76 (moffs16 (immediate nil
)
79 (moffs32 (immediate nil
)
96 (cr0) (cr2) (cr3) (cr4)
97 (dr0) (dr1) (dr2) (dr3)
98 (dr4) (dr5) (dr6) (dr7)
99 (ptr16-16 (immediate nil
))
100 (ptr16-32 (immediate nil
))
101 (m16-16 (immediate nil
))
102 (m16-32 (immediate nil
))
103 (m32real (immediate nil
))
104 (m64real (immediate nil
))
105 (m80real (immediate nil
))
106 (m16int (immediate nil
))
107 (m32int (immediate nil
))
108 (m64int (immediate nil
)))
110 ;;; ----------------------------------------------------------------
112 ;;; ----------------------------------------------------------------
114 (defclass operand
() ())
116 (defclass concrete-operand
(operand) ()
117 (:documentation
"Operands that correspond directly
118 to one of the x86 operand adressing modes."))
120 (defclass abstract-operand
(operand) ()
121 (:documentation
"Operands that are not concrete, for example
122 symbolic references. Abstract operands need to be resolved to concrete
123 operands at encoding-time."))
125 (defmethod print-object ((obj concrete-operand
) stream
)
126 (format stream
"~A" (operand-listform obj
))
129 (defmethod print-object ((obj abstract-operand
) stream
)
130 (format stream
"~A" (operand-listform obj
))
133 ;;; ----------------------------------------------------------------
134 ;;; Abstract operands
135 ;;; ----------------------------------------------------------------
137 (defun abstract-operand-to-offset (operand template instr env
)
138 (sign-extend (mod (- (operand-resolve-to-number operand env
)
139 (assemble-env-current-pc env
)
140 (template-instr-and-prefix-length template instr env
))
144 (defclass operand-label
(abstract-operand)
148 :accessor operand-label
)
151 :reader operand-user-size
154 (defmethod operand-user-size ((operand t
)) nil
)
156 (defmethod operand-listform ((operand operand-label
))
158 (operand-label operand
)
159 (operand-user-size operand
)))
161 (defmethod operand-resolve-to-number ((operand operand-label
) env
)
162 (assert (not (null env
)) ()
163 "Resolving ~A requires an assemble-environment." operand
)
164 (symtab-lookup-label (assemble-env-symtab env
)
165 (operand-label operand
)))
167 (defclass calculated-operand
(abstract-operand)
169 :initarg
:sub-operands
170 :accessor sub-operands
)
172 :initarg
:calculation
173 :reader operand-calculation
)
176 :reader operand-user-size
179 (defmethod operand-resolve-to-number ((operand calculated-operand
) env
)
180 (assert (not (null env
)) ()
181 "Resolving ~A requires an assemble-environment." operand
)
182 (apply (operand-calculation operand
)
183 (mapcar #'operand-resolve-to-number
184 (sub-operands operand
)
185 (let ((x (cons env nil
)))
186 (setf (cdr x
) x
))))) ; make circular one-list.
188 (defclass operand-number
(abstract-operand)
192 :reader operand-number
)))
194 (defmethod operand-listform ((operand operand-number
))
196 (operand-number operand
)))
198 (defmethod operand-resolve-to-number ((operand operand-number
) env
)
199 (declare (ignore env
))
200 (operand-number operand
))
202 ;;; ----------------------------------------------------------------
203 ;;; Concrete operands (modelling the "real world" x86 CPU)
204 ;;; ----------------------------------------------------------------
206 ;;; ----------------------------------------------------------------
208 ;;; ----------------------------------------------------------------
210 (defclass operand-immediate
(concrete-operand)
213 :accessor operand-value
)))
215 (defmethod operand-listform ((obj operand-immediate
))
218 (defmethod print-object ((obj operand-immediate
) stream
)
219 (if (and (not *print-readably
*)
222 (format stream
"~A" (slot-value obj
'value
))
224 (call-next-method obj stream
)))
226 ;;; ----------------------------------------------------------------
228 ;;; ----------------------------------------------------------------
230 (defclass operand-register
(concrete-operand)
233 :accessor operand-register
)))
235 (defmethod operand-listform ((obj operand-register
))
236 (operand-register obj
))
238 (defmethod print-object ((obj operand-register
) stream
)
239 (if (and (not *print-readably
*)
241 (progn (format stream
"%~A" (slot-value obj
'register
))
243 (call-next-method obj stream
)))
245 ;;; ----------------------------------------------------------------
247 ;;; ----------------------------------------------------------------
249 (defclass operand-memory
(concrete-operand)
252 ;;; ----------------------------------------------------------------
254 ;;; ----------------------------------------------------------------
256 (defclass operand-direct
(operand-memory)
257 ((address :accessor operand-address
259 (segment :accessor operand-segment
263 (defmethod operand-listform ((obj operand-direct
))
264 (if (null (operand-segment obj
))
265 (list (operand-address obj
))
266 (list (operand-segment obj
)
267 (operand-address obj
))))
269 (defmethod print-object ((obj operand-direct
) stream
)
270 (if (not *print-readably
*)
272 (format stream
"[~@[~A:~]~A]"
273 (operand-segment obj
)
274 (operand-address obj
))
276 (call-next-method obj stream
)))
278 ;;; ----------------------------------------------------------------
279 ;;; PC-Relative Pointer
280 ;;; ----------------------------------------------------------------
282 (defclass operand-rel-pointer
(operand-memory)
284 :accessor operand-offset
287 (defmethod operand-listform ((obj operand-rel-pointer
))
288 (list :pc
+ (operand-offset obj
)))
290 (defmethod print-object ((obj operand-rel-pointer
) stream
)
291 (if (not *print-readably
*)
293 (format stream
"%PC+~A" (slot-value obj
'offset
))
295 (call-next-method obj stream
)))
297 ;;; ----------------------------------------------------------------
298 ;;; Register-Relative pointer
299 ;;; ----------------------------------------------------------------
301 (defclass operand-indirect-register
(operand-memory)
303 :accessor operand-register
307 :accessor operand-register2
310 :accessor operand-offset
314 :type
(integer 0 8) ; scale for register (not register2)
316 :accessor operand-scale
319 (defmethod operand-listform ((obj operand-indirect-register
))
320 (with-slots (offset register scale register2
)
322 (append (unless (and (integerp offset
) (zerop offset
))
326 (list (list register scale
)))
330 (defmethod print-object ((obj operand-indirect-register
) stream
)
331 (if (not *print-readably
*)
332 (with-slots (offset register2 register scale
) obj
333 (format stream
"[~@[~A+~]~@[%~A+~]%~A~@[*~D~]]"
334 (unless (and (integerp offset
) (zerop offset
))
341 (call-next-method obj stream
)))
343 (defun resolve-indirect-register (operand env
)
344 (with-slots (register register2 offset scale
) operand
349 (make-instance 'operand-indirect-register
350 'offset
(symtab-lookup-label (assemble-env-symtab env
) offset
)
355 (make-instance 'operand-indirect-register
356 'offset
(apply (car offset
)
357 (mapcar #'(lambda (o)
361 (symtab-lookup-label (assemble-env-symtab env
) o
))))
367 (defun resolve-direct (operand env
)
368 (with-slots (address segment
) operand
369 (if (not (symbolp address
))
371 (make-instance 'operand-direct
372 'address
(symtab-lookup-label (assemble-env-symtab env
) address
)
375 ;;; ----------------------------------------------------------------
376 ;;; Definition of specialized operand classes
377 ;;; ----------------------------------------------------------------
379 (defvar *operand-classes
* (make-hash-table :test
#'equal
))
380 (defvar *operand-encoding-by-type
* (make-hash-table :test
#'eq
))
382 (defmacro def-operand-class
((operand-encoding operand-types
383 &optional
(reg-set (first operand-types
)))
384 (base-operand-class) slots
)
385 (let ((name (intern (format nil
"~A~S~{-~S~}" ; the name isn't really important
386 (symbol-name '#:operand-
)
387 operand-encoding operand-types
))))
389 (assert (subtypep (find-class ',base-operand-class
)
390 (find-class 'operand
))
392 "Base operand-class ~A is not an OPERAND class." ',base-operand-class
)
393 (defclass ,name
(,base-operand-class
) ,slots
)
394 (defmethod operand-class-register-set ((operand-encoding (eql (find-class ',name
))))
396 (defmethod operand-class-encoding ((operand-encoding (eql (find-class ',name
))))
397 (values ',operand-encoding
))
398 (defmethod operand-class-base-class ((operand-class (eql (find-class ',name
))))
399 (values (find-class ',base-operand-class
)))
400 ,@(loop for ot in operand-types
402 `((setf (gethash (cons ',operand-encoding
',ot
) *operand-classes
*)
404 (pushnew ',operand-encoding
405 (gethash ',ot
*operand-encoding-by-type
*)))))))
407 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
408 (defparameter +operand-types-indirect-modrm
+
409 '(r/m8 r
/m16 r
/m32 m m64
411 xmm
/m128 xmm
/m64 xmm
/m32
412 m32real m64real m80real
415 "This set of operand-types are pointers which are encoded the same way,
416 but differ in only in what they point to."))
418 (defmacro def-operand-class-imodrm
((operand-encoding
419 &optional
(reg-set nil
))
420 (base-operand-class) slots
)
421 `(def-operand-class (,operand-encoding
,+operand-types-indirect-modrm
+ ,reg-set
)
422 (,base-operand-class
) ,slots
))
425 (defun find-operand-class (operand-encoding operand-type
&key
(errorp t
))
426 "Locate the operand class that encodes <operand-type> into <operand-encoding>."
427 (let ((oc (gethash (cons operand-encoding operand-type
) *operand-classes
*)))
428 (unless (or oc
(not errorp
))
429 (error "couldn't find operand-class for (~A ~A)." operand-encoding operand-type
))
432 (defun find-operand-type-encodings (operand-type)
433 (gethash operand-type
*operand-encoding-by-type
*))
435 (defmethod operand-decode (operand (encoding (eql nil
)) instr-symbolic
)
436 "Fallback when no operand-encoding was specified."
437 (if (operand-class-encoding (class-of operand
))
438 (operand-decode operand
(operand-class-encoding (class-of operand
)) instr-symbolic
)
439 (call-next-method operand encoding instr-symbolic
)))
442 ;;; ----------------------------------------------------------------
443 ;;; Operand unification
444 ;;; ----------------------------------------------------------------
446 (defgeneric operand-and-encoding-unifies-p
(operand encoding operand-type
)
447 (:documentation
"This predicate determines if an operand instance may
448 be encoded in a particular encoding and operand-type."))
450 (defmethod operand-and-encoding-unifies-p (operand encoding operand-type
)
451 "If no specialized method exists, the operand and encoding don't unify."
452 (declare (ignore operand encoding operand-type
))
455 (defun operand-unifies-with (operand operand-type
)
456 "Return a list of all encodings this operand unifies with."
457 (loop for encoding in
(find-operand-type-encodings operand-type
)
458 when
(operand-and-encoding-unifies-p operand encoding operand-type
)
463 (defgeneric operand-and-encoding-unify
(operand encoding operand-type template instr env
)
464 (:documentation
"If OPERAND cannot be encoded in ENCODING and
465 OPERAND-TYPE, NIL is returned. Otherwise, a concretized OPERAND
466 is returned (if OPERAND is concrete, the same operand is typically
469 (defmethod operand-and-encoding-unify (operand encoding operand-type template instr env
)
470 "If no specialized method exists, the operand and encoding don't unify."
471 (declare (ignore operand encoding operand-type template instr env
))
474 ;;; ----------------------------------------------------------------
475 ;;; General, plain operand classes
476 ;;; ----------------------------------------------------------------
480 (def-operand-class (plain-displacement (displacement)) (operand-direct) ())
482 (defmethod operand-and-encoding-unify ((operand operand-direct
)
483 (encoding (eql 'plain-displacement
))
487 (declare (ignore operand-type instr
))
488 (let ((resolved-operand (resolve-direct operand env
)))
489 (with-slots (address segment
)
492 (<= 0 address
(expt 2 (* 8 (template-instr-displacement-numo template
))))
495 (defmethod operand-decode ((operand operand-direct
)
496 (encoding (eql 'plain-displacement
))
498 (setf (operand-address operand
)
499 (slot-value instr-symbolic
'displacement
))
502 (defmethod operand-encode ((operand operand-direct
)
503 (encoding (eql 'plain-displacement
))
506 (declare (ignore operand-type
))
507 (setf (slot-value instr-symbolic
'displacement
)
508 (operand-address operand
))
509 (values instr-symbolic
'(displacement)))
513 ;;;(def-operand-class (plain-immediate (immediate)) (operand-immediate) ())
515 ;;;(defmethod operand-and-encoding-unify ((operand operand-immediate)
516 ;;; (encoding (eql 'plain-immediate))
520 ;;; (declare (ignore operand-type instr env))
521 ;;; (with-slots (value)
523 ;;; (and (<= 0 value (expt 2 (* 8 (template-instr-immediate-numo template))))
526 ;;;(defmethod operand-decode ((operand operand-immediate)
527 ;;; (encoding (eql 'plain-immediate))
529 ;;; (setf (operand-value operand)
530 ;;; (slot-value instr-symbolic 'immediate))
531 ;;; (values operand))
533 ;;;(defmethod operand-encode ((operand operand-immediate)
534 ;;; (encoding (eql 'plain-immediate))
537 ;;; (declare (ignore operand-type))
538 ;;; (setf (slot-value instr-symbolic 'immediate)
539 ;;; (operand-value operand))
540 ;;; (values instr-symbolic '(immediate)))
543 ;;; ----------------------------------------------------------------
544 ;;; Specialized operand classes
545 ;;; ----------------------------------------------------------------
548 ;;; Direct register operands encoded in the REG of MODR/M.
550 (def-operand-class (register-reg (r8)) (operand-register) ())
551 (def-operand-class (register-reg (r16)) (operand-register) ())
552 (def-operand-class (register-reg (r32)) (operand-register) ())
553 (def-operand-class (register-reg (sreg)) (operand-register) ())
554 (def-operand-class (register-reg (mm)) (operand-register) ()) ; MMX
555 (def-operand-class (register-reg (xmm)) (operand-register) ()) ; SIMD
557 (defmethod operand-and-encoding-unify ((operand operand-register
)
558 (encoding (eql 'register-reg
))
562 (declare (ignore template instr env
))
563 (and (decode-set (find-register-encode-set operand-type
)
564 (slot-value operand
'register
)
568 (defmethod operand-decode ((operand operand-register
)
569 (encoding (eql 'register-reg
))
571 (setf (operand-register operand
)
572 (decode-set (find-register-decode-set (operand-class-register-set (class-of operand
)))
573 (slot-value instr-symbolic
'reg
)))
574 (assert (not (null (operand-register operand
)))
575 ((operand-register operand
))
576 "Unable to decode operand value ~A from set ~A"
577 (slot-value instr-symbolic
'reg
)
578 (find-register-decode-set (operand-class-register-set (class-of operand
))))
581 (defmethod operand-encode ((operand operand-register
)
582 (encoding (eql 'register-reg
))
585 (setf (slot-value instr-symbolic
'reg
)
586 (decode-set (find-register-encode-set operand-type
)
587 (operand-register operand
)))
588 (values instr-symbolic
'(reg)))
591 ;;; Direct register operands encoded in the R/M of of MODR/M.
593 (def-operand-class (register-r/m
(r/m8
)) (operand-register) ())
594 (def-operand-class (register-r/m
(r/m16
)) (operand-register) ())
595 (def-operand-class (register-r/m
(r/m32
)) (operand-register) ())
596 (def-operand-class (register-r/m
(mm/m64
)) (operand-register) ()) ; MMX
597 (def-operand-class (register-r/m
(xmm/m128 xmm
/m64 xmm
/m32
)) (operand-register) ()) ; SIMD
599 (defmethod operand-and-encoding-unify ((operand operand-register
)
600 (encoding (eql 'register-r
/m
))
604 (declare (ignore template instr env
))
605 (and (decode-set (find-register-encode-set operand-type
)
606 (slot-value operand
'register
)
610 (defmethod operand-decode ((operand operand-register
)
611 (encoding (eql 'register-r
/m
))
613 (assert (= #b11
(slot-value instr-symbolic
'mod
)))
614 (setf (operand-register operand
)
615 (decode-set (find-register-decode-set (operand-class-register-set (class-of operand
)))
616 (slot-value instr-symbolic
'r
/m
)))
619 (defmethod operand-encode ((operand operand-register
)
620 (encoding (eql 'register-r
/m
))
623 (with-slots (mod r
/m
)
626 r
/m
(decode-set (find-register-encode-set operand-type
)
627 (slot-value operand
'register
))))
628 (values instr-symbolic
'(mod r
/m
)))
631 ;;; Indirect register operand encoded in R/M,
632 ;;; with Mod=00 and R/M /= {#b100, #b101}
634 (def-operand-class-imodrm (indirect-register-mod00) (operand-indirect-register) ())
636 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
637 (encoding (eql 'indirect-register-mod00
))
641 (declare (ignore template instr
))
642 (let ((resolved-operand (resolve-indirect-register operand env
)))
643 (with-slots (offset register register2 scale
)
645 (and (member operand-type
+operand-types-indirect-modrm
+)
649 (member register
'(eax ecx edx ebx esi edi
))
652 (defmethod operand-decode ((operand operand-indirect-register
)
653 (encoding (eql 'indirect-register-mod00
))
655 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
656 (assert (/= #b100
#b101
(slot-value instr-symbolic
'r
/m
)))
657 (with-slots (register register2 offset scale
)
659 (setf register
(decode-set (find-register-decode-set 'r
/m32-00
)
660 (slot-value instr-symbolic
'r
/m
))
666 (defmethod operand-encode ((operand operand-indirect-register
)
667 (encoding (eql 'indirect-register-mod00
))
670 (declare (ignore operand-type
))
671 (with-slots (mod r
/m
)
674 r
/m
(decode-set (find-register-encode-set 'r
/m32-00
)
675 (slot-value operand
'register
))))
676 (values instr-symbolic
'(mod r
/m
)))
679 ;;; Indirect register with MOD=#b00, R/M=#b100 in ModR/M
680 ;;; and neither index=#b100 nor base=#b101 in SIB.
682 (def-operand-class-imodrm (indirect-register-00-sib) (operand-indirect-register) ())
684 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
685 (encoding (eql 'indirect-register-00-sib
))
689 (declare (ignore template instr
))
690 (let ((resolved-operand (resolve-indirect-register operand env
)))
691 (with-slots (register register2 offset scale
)
693 (and (member operand-type
+operand-types-indirect-modrm
+)
695 (member register
'(eax ecx edx ebx ebp esi edi
))
696 (member register2
'(eax ecx edx ebx esp esi edi
))
697 (member scale
'(1 2 4 8))
700 (defmethod operand-decode ((operand operand-indirect-register
)
701 (encoding (eql 'indirect-register-00-sib
))
703 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
704 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
705 (assert (/= #b100
(slot-value instr-symbolic
'index
)))
706 (assert (/= #b101
(slot-value instr-symbolic
'base
)))
707 (with-slots (register register2 offset scale
)
709 (setf register2
(decode-set (find-register-decode-set 'sib-base-00
)
710 (slot-value instr-symbolic
'base
))
711 register
(decode-set (find-register-decode-set 'sib-index
)
712 (slot-value instr-symbolic
'index
))
713 scale
(expt 2 (slot-value instr-symbolic
'scale
))
716 (defmethod operand-encode ((operand operand-indirect-register
)
717 (encoding (eql 'indirect-register-00-sib
))
720 (declare (ignore operand-type
))
721 (with-slots (mod r
/m base index scale
)
725 base
(decode-set (find-register-encode-set 'sib-base-00
)
726 (slot-value operand
'register2
))
727 index
(decode-set (find-register-encode-set 'sib-index
)
728 (slot-value operand
'register
))
729 scale
(cdr (assoc (slot-value operand
'scale
)
730 '((0 .
0) (1 .
0) (2 .
1) (4 .
2) (8 .
3))))))
731 (values instr-symbolic
'(base index scale
)))
733 ;;; Indirect register with MOD=#b00, R/M=#b100 in ModR/M
734 ;;; and base=#b101 and index/=#b100 in SIB.
736 (def-operand-class-imodrm (indirect-register-00-sib-base5) (operand-indirect-register) ())
738 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
739 (encoding (eql 'indirect-register-00-sib-base5
))
743 (declare (ignore template instr
))
744 (assert (member operand-type
+operand-types-indirect-modrm
+))
745 (let ((resolved-operand (resolve-indirect-register operand env
)))
746 (with-slots (register register2 scale
)
749 (member register
'(eax ecx edx ebx ebp esi edi
))
750 (member scale
'(1 2 4 8))
753 (defmethod operand-decode ((operand operand-indirect-register
)
754 (encoding (eql 'indirect-register-00-sib-base5
))
756 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
757 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
758 (assert (= #b101
(slot-value instr-symbolic
'base
)))
759 (assert (/= #b100
(slot-value instr-symbolic
'index
)))
760 (with-slots (register register2 offset scale
)
762 (setf register
(decode-set (find-register-decode-set 'sib-index
)
763 (slot-value instr-symbolic
'index
))
765 offset
(realpart (slot-value instr-symbolic
'displacement
))
766 scale
(expt 2 (slot-value instr-symbolic
'scale
))))
768 (defmethod operand-encode ((operand operand-indirect-register
)
769 (encoding (eql 'indirect-register-00-sib-base5
))
772 (declare (ignore operand-type
))
773 (with-slots (mod r
/m base index scale displacement
)
778 index
(decode-set (find-register-encode-set 'sib-index
)
779 (slot-value operand
'register
))
780 scale
(1- (integer-length (slot-value operand
'scale
)))
781 displacement
(realpart (slot-value operand
'offset
))))
782 (values instr-symbolic
'(mod r
/m base index scale
)))
785 ;;; Indirect register with MOD=#b00, R/M=#b100 in ModR/M
786 ;;; and base/=#b101 and index=#b100 in SIB.
788 (def-operand-class-imodrm (indirect-register-00-sib-index4) (operand-indirect-register) ())
790 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
791 (encoding (eql 'indirect-register-00-sib-index4
))
795 (declare (ignore template instr
))
796 (assert (member operand-type
+operand-types-indirect-modrm
+))
797 (let ((resolved-operand (resolve-indirect-register operand env
)))
798 (with-slots (register register2 offset scale
)
804 (member register
'(eax ecx edx ebx esp esi edi
))
807 (defmethod operand-decode ((operand operand-indirect-register
)
808 (encoding (eql 'indirect-register-00-sib-index4
))
810 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
811 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
812 (assert (= #b100
(slot-value instr-symbolic
'index
)))
813 (assert (/= #b101
(slot-value instr-symbolic
'base
)))
814 (with-slots (register offset scale
)
816 (setf register
(decode-set (find-register-decode-set 'sib-base-00
)
817 (slot-value instr-symbolic
'base
))
822 (defmethod operand-encode ((operand operand-indirect-register
)
823 (encoding (eql 'indirect-register-00-sib-index4
))
826 (declare (ignore operand-type
))
827 (with-slots (mod r
/m index base scale
)
832 base
(decode-set (find-register-encode-set 'sib-base-00
)
833 (slot-value operand
'register
))
835 (values instr-symbolic
'(mod r
/m index base scale
)))
838 ;;; Indirect pointer with MOD=#b00, R/M=#b100 in ModR/M
839 ;;; and base=#b101 and index=#b100 in SIB.
841 (def-operand-class-imodrm (indirect-pointer-00-sib-index4-base5) (operand-direct) ())
843 (defmethod operand-and-encoding-unify ((operand operand-direct
)
844 (encoding (eql 'indirect-pointer-00-sib-index4-base5
))
848 (declare (ignore template instr
))
849 (let ((resolved-operand (resolve-direct operand env
)))
850 (assert (member operand-type
+operand-types-indirect-modrm
+))
851 (and (null (slot-value resolved-operand
'segment
))
854 (defmethod operand-decode ((operand operand-direct
)
855 (encoding (eql 'indirect-pointer-00-sib-index4-base5
))
857 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
858 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
859 (assert (= #b101
(slot-value instr-symbolic
'base
)))
860 (assert (= #b100
(slot-value instr-symbolic
'index
)))
861 (setf (slot-value operand
'address
)
862 (realpart (slot-value instr-symbolic
'displacement
)))
865 (defmethod operand-encode ((operand operand-direct
)
866 (encoding (eql 'indirect-pointer-00-sib-index4-base5
))
869 (declare (ignore operand-type
))
870 (with-slots (mod r
/m base index scale displacement
)
877 displacement
(slot-value operand
'address
)))
878 (values instr-symbolic
'(mod r
/m base index displacement
)))
880 ;;; Indirect pointer with MOD=#b00, R/M=#b101 in ModR/M
882 (def-operand-class-imodrm (indirect-pointer-00) (operand-direct) ())
884 (defmethod operand-and-encoding-unify ((operand operand-direct
)
885 (encoding (eql 'indirect-pointer-00
))
889 (declare (ignore template instr
))
890 (assert (member operand-type
+operand-types-indirect-modrm
+))
891 (let ((resolved-operand (resolve-direct operand env
)))
892 (and (null (slot-value resolved-operand
'segment
))
895 (defmethod operand-decode ((operand operand-direct
)
896 (encoding (eql 'indirect-pointer-00
))
898 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
899 (assert (= #b101
(slot-value instr-symbolic
'r
/m
)))
900 (setf (slot-value operand
'address
)
901 (realpart (slot-value instr-symbolic
'displacement
)))
904 (defmethod operand-encode ((operand operand-direct
)
905 (encoding (eql 'indirect-pointer-00
))
908 (declare (ignore operand-type
))
909 (with-slots (mod r
/m displacement
)
913 displacement
(realpart (slot-value operand
'address
))))
914 (values instr-symbolic
'(mod r
/m displacement
)))
917 ;;; Indirect register with MOD=#b01, R/M/=#b100 in ModR/M.
919 (def-operand-class-imodrm (indirect-register-01) (operand-indirect-register) ())
921 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
922 (encoding (eql 'indirect-register-01
))
926 (declare (ignore template instr
))
927 (assert (member operand-type
+operand-types-indirect-modrm
+))
928 (let ((resolved-operand (resolve-indirect-register operand env
)))
929 (with-slots (register register2 offset scale
)
932 (member register
'(eax ecx edx ebx ebp esi edi
))
937 (defmethod operand-decode ((operand operand-indirect-register
)
938 (encoding (eql 'indirect-register-01
))
940 (assert (= #b01
(slot-value instr-symbolic
'mod
)))
941 (assert (/= #b100
(slot-value instr-symbolic
'r
/m
)))
942 (with-slots (mod r
/m displacement
)
944 (with-slots (register offset
)
946 (setf register
(decode-set (find-register-decode-set 'r
/m32-01
)
948 offset
(realpart displacement
))))
951 (defmethod operand-encode ((operand operand-indirect-register
)
952 (encoding (eql 'indirect-register-01
))
955 (declare (ignore operand-type
))
956 (with-slots (mod r
/m displacement
)
959 r
/m
(decode-set (find-register-encode-set 'r
/m32-01
)
960 (slot-value operand
'register
))
961 displacement
(realpart (slot-value operand
'offset
))))
962 (values instr-symbolic
'(mod r
/m displacement
)))
964 ;;; Indirect register with MOD=#b01, R/M=#b100 in ModR/M,
965 ;;; index/=#b100 in SIB.
967 (def-operand-class-imodrm (indirect-register-01-sib) (operand-indirect-register) ())
969 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
970 (encoding (eql 'indirect-register-01-sib
))
974 (declare (ignore template instr
))
975 (assert (member operand-type
+operand-types-indirect-modrm
+))
976 (let ((resolved-operand (resolve-indirect-register operand env
)))
977 (with-slots (register register2 offset scale
)
980 ((and (member register
'(eax ecx edx ebx ebp esi edi
))
981 (member register2
'(eax ecx edx ebx esp ebp esi edi
))
982 (member scale
'(1 2 4 8) :test
#'=)
983 (<= -
128 offset
127))
985 ((and (member register2
'(eax ecx edx ebx ebp esi edi
))
986 (member register
'(eax ecx edx ebx esp ebp esi edi
))
988 (<= -
128 offset
127))
989 ;; exchange register and register2
990 (make-instance 'operand-indirect-register
997 (defmethod operand-decode ((operand operand-indirect-register
)
998 (encoding (eql 'indirect-register-01-sib
))
1000 (assert (= #b01
(slot-value instr-symbolic
'mod
)))
1001 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
1002 (assert (/= #b100
(slot-value instr-symbolic
'index
)))
1003 (with-slots (register register2 scale offset
)
1005 (setf register
(decode-set (find-register-decode-set 'sib-index
)
1006 (slot-value instr-symbolic
'index
))
1007 scale
(expt 2 (slot-value instr-symbolic
'scale
))
1008 register2
(decode-set (find-register-decode-set 'sib-base
)
1009 (slot-value instr-symbolic
'base
))
1010 offset
(realpart (slot-value instr-symbolic
'displacement
)))) ; disp8
1014 (defmethod operand-encode ((operand operand-indirect-register
)
1015 (encoding (eql 'indirect-register-01-sib
))
1018 (declare (ignore operand-type
))
1019 (with-slots (mod r
/m scale index base displacement
)
1023 index
(decode-set (find-register-encode-set 'sib-index
)
1024 (slot-value operand
'register
))
1025 scale
(1- (integer-length (slot-value operand
'scale
)))
1026 base
(decode-set (find-register-encode-set 'sib-base
)
1027 (slot-value operand
'register2
))
1028 displacement
(slot-value operand
'offset
)))
1029 (values instr-symbolic
'(mod r
/m scale index base displacement
)))
1032 ;;; Indirect register with MOD=#b01, R/M=#b100 in ModR/M,
1033 ;;; index=#b100 in SIB.
1035 (def-operand-class-imodrm (indirect-register-01-sib-index4) (operand-indirect-register) ())
1037 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
1038 (encoding (eql 'indirect-register-01-sib-index4
))
1042 (declare (ignore template instr
))
1043 (assert (member operand-type
+operand-types-indirect-modrm
+))
1044 (let ((resolved-operand (resolve-indirect-register operand env
)))
1045 (with-slots (register register2 offset scale
)
1047 (and (member register
'(eax ecx edx ebx esp ebp esi edi
))
1049 (<= -
128 offset
127)
1051 resolved-operand
))))
1053 (defmethod operand-decode ((operand operand-indirect-register
)
1054 (encoding (eql 'indirect-register-01-sib-index4
))
1056 (assert (= #b01
(slot-value instr-symbolic
'mod
)))
1057 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
1058 (assert (= #b100
(slot-value instr-symbolic
'index
)))
1059 (with-slots (register offset scale
)
1061 (setf register
(decode-set (find-register-decode-set 'sib-base
)
1062 (slot-value instr-symbolic
'base
))
1063 offset
(realpart (slot-value instr-symbolic
'displacement
))
1067 (defmethod operand-encode ((operand operand-indirect-register
)
1068 (encoding (eql 'indirect-register-01-sib-index4
))
1071 (declare (ignore operand-type
))
1072 (with-slots (mod r
/m index base scale displacement
)
1077 base
(decode-set (find-register-encode-set 'sib-base
)
1078 (slot-value operand
'register
))
1079 scale
0 ; don't care
1080 displacement
(slot-value operand
'offset
)))
1081 (values instr-symbolic
'(mod r
/m index base scale displacement
)))
1084 ;;; Indirect register with MOD=#b10, R/M/=#b100 in ModR/M.
1086 (def-operand-class-imodrm (indirect-register-10) (operand-indirect-register) ())
1088 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
1089 (encoding (eql 'indirect-register-10
))
1093 (declare (ignore template instr
))
1094 (assert (member operand-type
+operand-types-indirect-modrm
+))
1095 (let ((resolved-operand (resolve-indirect-register operand env
)))
1096 (with-slots (register register2 offset scale
)
1099 (member register
'(eax ecx edx ebx ebp esi edi
))
1101 (<= #x-80000000 offset
#xffffffff
)
1102 resolved-operand
))))
1104 (defmethod operand-decode ((operand operand-indirect-register
)
1105 (encoding (eql 'indirect-register-10
))
1107 (assert (= #b10
(slot-value instr-symbolic
'mod
)))
1108 (assert (/= #b100
(slot-value instr-symbolic
'r
/m
)))
1109 (with-slots (mod r
/m displacement
)
1111 (with-slots (register offset
)
1113 (setf register
(decode-set (find-register-decode-set 'r
/m32-01
)
1115 offset
(realpart displacement
))))
1117 (defmethod operand-encode ((operand operand-indirect-register
)
1118 (encoding (eql 'indirect-register-10
))
1121 (declare (ignore operand-type
))
1122 (with-slots (mod r
/m displacement
)
1125 r
/m
(decode-set (find-register-encode-set 'r
/m32-01
)
1126 (slot-value operand
'register
))
1127 displacement
(realpart (slot-value operand
'offset
))))
1128 (values instr-symbolic
'(mod r
/m displacement
)))
1130 ;;; Indirect register with MOD=#b10, R/M=#b100 in ModR/M,
1131 ;;; index/=#b100 in SIB.
1133 (def-operand-class-imodrm (indirect-register-10-sib) (operand-indirect-register) ())
1135 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
1136 (encoding (eql 'indirect-register-10-sib
))
1140 (declare (ignore template instr
))
1141 (assert (member operand-type
+operand-types-indirect-modrm
+))
1142 (let ((resolved-operand (resolve-indirect-register operand env
)))
1143 (with-slots (register register2 offset scale
)
1145 (and (member register
'(eax ecx edx ebx ebp esi edi
))
1146 (member register2
'(eax ecx edx ebx esp ebp esi edi
))
1147 (member scale
'(1 2 4 8))
1148 (<= #x-80000000 offset
#xffffffff
)
1149 resolved-operand
))))
1151 (defmethod operand-decode ((operand operand-indirect-register
)
1152 (encoding (eql 'indirect-register-10-sib
))
1154 (assert (= #b10
(slot-value instr-symbolic
'mod
)))
1155 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
1156 (assert (/= #b100
(slot-value instr-symbolic
'index
)))
1157 (with-slots (register register2 scale offset
)
1159 (setf register
(decode-set (find-register-decode-set 'sib-index
)
1160 (slot-value instr-symbolic
'index
))
1161 scale
(expt 2 (slot-value instr-symbolic
'scale
))
1162 register2
(decode-set (find-register-decode-set 'sib-base
)
1163 (slot-value instr-symbolic
'base
))
1164 offset
(realpart (slot-value instr-symbolic
'displacement
)))) ; disp8
1168 (defmethod operand-encode ((operand operand-indirect-register
)
1169 (encoding (eql 'indirect-register-10-sib
))
1172 (declare (ignore operand-type
))
1173 (with-slots (mod r
/m scale index base displacement
)
1177 index
(decode-set (find-register-encode-set 'sib-index
)
1178 (slot-value operand
'register
))
1179 scale
(1- (integer-length (slot-value operand
'scale
)))
1180 base
(decode-set (find-register-encode-set 'sib-base
)
1181 (slot-value operand
'register2
))
1182 displacement
(slot-value operand
'offset
)))
1183 (values instr-symbolic
'(mod r
/m scale index base displacement
)))
1185 ;;; Indirect register with MOD=#b10, R/M=#b100 in ModR/M,
1186 ;;; index=#b100 in SIB.
1188 (def-operand-class-imodrm (indirect-register-10-sib-index4) (operand-indirect-register) ())
1190 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
1191 (encoding (eql 'indirect-register-10-sib-index4
))
1195 (declare (ignore template instr
))
1196 (assert (member operand-type
+operand-types-indirect-modrm
+))
1197 (let ((resolved-operand (resolve-indirect-register operand env
)))
1198 (with-slots (register register2 offset scale
)
1200 (and (member register
'(eax ecx edx ebx esp ebp esi edi
))
1202 (<= #x-80000000 offset
#xffffffff
)
1204 resolved-operand
))))
1206 (defmethod operand-decode ((operand operand-indirect-register
)
1207 (encoding (eql 'indirect-register-10-sib-index4
))
1209 (assert (= #b10
(slot-value instr-symbolic
'mod
)))
1210 (assert (= #b100
(slot-value instr-symbolic
'r
/m
)))
1211 (assert (= #b100
(slot-value instr-symbolic
'index
)))
1212 (with-slots (register offset scale
)
1214 (setf register
(decode-set (find-register-decode-set 'sib-base
)
1215 (slot-value instr-symbolic
'base
))
1216 offset
(realpart (slot-value instr-symbolic
'displacement
))
1220 (defmethod operand-encode ((operand operand-indirect-register
)
1221 (encoding (eql 'indirect-register-10-sib-index4
))
1224 (declare (ignore operand-type
))
1225 (with-slots (mod r
/m index base scale displacement
)
1230 base
(decode-set (find-register-encode-set 'sib-base
)
1231 (slot-value operand
'register
))
1232 scale
0 ; don't care
1233 displacement
(slot-value operand
'offset
)))
1234 (values instr-symbolic
'(mod r
/m index base scale displacement
)))
1236 ;;; Indirect 16-bit register with MOD=#b00, R/M/=#b110 in ModR/M,
1238 (def-operand-class-imodrm (16bit-indirect-register-mod00) (operand-indirect-register) ())
1240 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
1241 (encoding (eql '16bit-indirect-register-mod00
))
1245 (declare (ignore template instr
))
1246 (assert (member operand-type
+operand-types-indirect-modrm
+))
1247 (let ((resolved-operand (resolve-indirect-register operand env
)))
1248 (with-slots (register register2 offset scale
)
1253 (and (member register
'(bx bp
))
1254 (member register2
'(si di
)))
1255 (member register
'(si di bx
)))
1256 resolved-operand
))))
1258 (defmethod operand-decode ((operand operand-indirect-register
)
1259 (encoding (eql '16bit-indirect-register-mod00
))
1261 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
1262 (assert (/= #b110
(slot-value instr-symbolic
'r
/m
)))
1263 (with-slots (register register2 offset scale
)
1265 (destructuring-bind (r1 . r2
)
1266 (decode-set (find-register-decode-set 'r
/m-16bit
)
1267 (slot-value instr-symbolic
'r
/m
))
1274 (defmethod operand-encode ((operand operand-indirect-register
)
1275 (encoding (eql '16bit-indirect-register-mod00
))
1278 (declare (ignore operand-type
))
1279 (with-slots (mod r
/m
)
1282 r
/m
(decode-set (find-register-encode-set 'r
/m-16bit
)
1283 (cons (slot-value operand
'register
)
1284 (slot-value operand
'register2
)))))
1285 (values instr-symbolic
'(mod r
/m
)))
1287 ;;; Indirect 16bit pointer with MOD=#b00, R/M=#b110 in ModR/M.
1289 (def-operand-class-imodrm (16bit-indirect-pointer) (operand-direct) ())
1291 (defmethod operand-and-encoding-unify ((operand operand-direct
)
1292 (encoding (eql '16bit-indirect-pointer
))
1296 (declare (ignore template instr
))
1297 (assert (member operand-type
+operand-types-indirect-modrm
+))
1298 (let ((resolved-operand (resolve-direct operand env
)))
1299 (with-slots (address segment
)
1302 (<= 0 address
#xffff
)
1303 resolved-operand
))))
1305 (defmethod operand-decode ((operand operand-direct
)
1306 (encoding (eql '16bit-indirect-pointer
))
1308 (assert (= #b00
(slot-value instr-symbolic
'mod
)))
1309 (assert (= #b110
(slot-value instr-symbolic
'r
/m
)))
1310 (with-slots (address)
1312 (setf address
(realpart (slot-value instr-symbolic
'displacement
))))
1315 (defmethod operand-encode ((operand operand-direct
)
1316 (encoding (eql '16bit-indirect-pointer
))
1319 (declare (ignore operand-type
))
1320 (with-slots (mod r
/m displacement
)
1324 displacement
(slot-value operand
'address
)))
1325 (values instr-symbolic
'(mod r
/m displacement
)))
1327 ;;; Indirect 16-bit register with MOD=#b01 in ModR/M.
1329 (def-operand-class-imodrm (16bit-indirect-register-mod01) (operand-indirect-register) ())
1331 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
1332 (encoding (eql '16bit-indirect-register-mod01
))
1336 (declare (ignore template instr
))
1337 (assert (member operand-type
+operand-types-indirect-modrm
+))
1338 (let ((resolved-operand (resolve-indirect-register operand env
)))
1339 (with-slots (register register2 offset scale
)
1342 (<= -
128 offset
127)
1344 (and (member register
'(bx bp
))
1345 (member register2
'(si di
)))
1346 (member register
'(si di bp bx
)))
1347 resolved-operand
))))
1349 (defmethod operand-decode ((operand operand-indirect-register
)
1350 (encoding (eql '16bit-indirect-register-mod01
))
1352 (assert (= #b01
(slot-value instr-symbolic
'mod
)))
1353 (with-slots (register register2 offset scale
)
1355 (destructuring-bind (r1 . r2
)
1356 (decode-set (find-register-decode-set 'r
/m-16bit
)
1357 (slot-value instr-symbolic
'r
/m
))
1360 offset
(sign-extend (realpart (slot-value instr-symbolic
'displacement
)) 1)
1364 (defmethod operand-encode ((operand operand-indirect-register
)
1365 (encoding (eql '16bit-indirect-register-mod01
))
1368 (declare (ignore operand-type
))
1369 (with-slots (mod r
/m displacement
)
1372 r
/m
(decode-set (find-register-encode-set 'r
/m-16bit
)
1373 (cons (slot-value operand
'register
)
1374 (slot-value operand
'register2
)))
1375 displacement
(slot-value operand
'offset
)))
1376 (values instr-symbolic
'(mod r
/m displacement
)))
1378 ;;; Indirect 16-bit register with MOD=#b10 in ModR/M.
1380 (def-operand-class-imodrm (16bit-indirect-register-mod10) (operand-indirect-register) ())
1382 (defmethod operand-and-encoding-unify ((operand operand-indirect-register
)
1383 (encoding (eql '16bit-indirect-register-mod10
))
1387 (declare (ignore template instr
))
1388 (assert (member operand-type
+operand-types-indirect-modrm
+))
1389 (let ((resolved-operand (resolve-indirect-register operand env
)))
1390 (with-slots (register register2 offset scale
)
1393 (<= 0 offset
#xffff
)
1395 (and (member register
'(bx bp
))
1396 (member register2
'(si di
)))
1397 (member register
'(si di bp bx
)))
1398 resolved-operand
))))
1400 (defmethod operand-decode ((operand operand-indirect-register
)
1401 (encoding (eql '16bit-indirect-register-mod10
))
1403 (assert (= #b10
(slot-value instr-symbolic
'mod
)))
1404 (with-slots (register register2 offset scale
)
1406 (destructuring-bind (r1 . r2
)
1407 (decode-set (find-register-decode-set 'r
/m-16bit
)
1408 (slot-value instr-symbolic
'r
/m
))
1411 offset
(realpart (slot-value instr-symbolic
'displacement
))
1415 (defmethod operand-encode ((operand operand-indirect-register
)
1416 (encoding (eql '16bit-indirect-register-mod10
))
1419 (declare (ignore operand-type
))
1420 (assert (<= 0 (slot-value operand
'offset
) #xffff
))
1421 (with-slots (mod r
/m displacement
)
1424 r
/m
(decode-set (find-register-encode-set 'r
/m-16bit
)
1425 (cons (slot-value operand
'register
)
1426 (slot-value operand
'register2
)))
1427 displacement
(slot-value operand
'offset
)))
1428 (values instr-symbolic
'(mod r
/m displacement
)))
1430 ;;; Absolute pointer encoded in the moffs operand-type
1432 (def-operand-class (abs-pointer-moffs (moffs8 moffs16 moffs32
))
1433 (operand-direct) ())
1435 (defmethod operand-and-encoding-unify ((operand operand-direct
)
1436 (encoding (eql 'abs-pointer-moffs
))
1440 (declare (ignore template instr
))
1441 (let ((resolved-operand (resolve-direct operand env
)))
1442 (with-slots (address)
1446 (moffs8 (<= 0 address
#xff
))
1447 (moffs16 (<= 0 address
#xffff
))
1448 (moffs32 (<= 0 address
#xffffffff
)))
1449 resolved-operand
))))
1451 (defmethod operand-decode ((operand operand-direct
)
1452 (encoding (eql 'abs-pointer-moffs
))
1454 (with-slots (address)
1456 (setf address
(realpart (slot-value instr-symbolic
'displacement
))))
1459 (defmethod operand-encode ((operand operand-direct
)
1460 (encoding (eql 'abs-pointer-moffs
))
1463 (declare (ignore operand-type
))
1464 (with-slots (displacement)
1466 (setf displacement
(slot-value operand
'address
)))
1467 (values instr-symbolic
'(displacement)))
1469 ;;; Register constants (no encoding)
1471 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
1472 (defparameter +constant-register-operands
+
1479 dr0 dr1 dr2 dr3 dr4 dr5 dr6 dr7
)))
1481 (defmacro def-many-constant-registers
(cr-list)
1483 (loop for cr in
(symbol-value cr-list
)
1484 collect
`(def-operand-class (register-constant (,cr
)) (operand-register) ()))))
1486 (def-many-constant-registers +constant-register-operands
+)
1488 (defmethod operand-and-encoding-unify ((operand operand-register
)
1489 (encoding (eql 'register-constant
))
1493 (declare (ignore template instr env
))
1494 (assert (member operand-type
+constant-register-operands
+))
1495 (and (eq operand-type
1496 (slot-value operand
'register
))
1499 (defmethod operand-decode ((operand operand-register
)
1500 (encoding (eql 'register-constant
))
1502 (declare (ignore instr-symbolic
))
1503 (with-slots (register)
1505 (setf register
(operand-class-register-set (class-of operand
))))
1508 (defmethod operand-encode ((operand operand-register
)
1509 (encoding (eql 'register-constant
))
1512 (declare (ignore operand-type
))
1513 (values instr-symbolic
'()))
1516 ;;; Immediate constants (no encoding)
1518 (def-operand-class (register-constant (1)) (operand-immediate) ())
1520 (defmethod operand-and-encoding-unify ((operand operand-immediate
)
1521 (encoding (eql 'register-constant
))
1525 (declare (ignore template instr env
))
1526 (and (= operand-type
1527 (slot-value operand
'value
))
1530 (defmethod operand-decode ((operand operand-immediate
)
1531 (encoding (eql 'register-constant
))
1533 (declare (ignore instr-symbolic
))
1536 (setf value
(operand-class-register-set (class-of operand
))))
1539 (defmethod operand-encode ((operand operand-immediate
)
1540 (encoding (eql 'register-constant
))
1543 (declare (ignore operand-type
))
1544 (values instr-symbolic
'()))
1547 ;;; Register encoded in the opcode (plus-format).
1549 (def-operand-class (register-plus (+r8
)) (operand-register) ())
1550 (def-operand-class (register-plus (+r16
)) (operand-register) ())
1551 (def-operand-class (register-plus (+r32
)) (operand-register) ())
1553 (defmethod operand-and-encoding-unify ((operand operand-register
)
1554 (encoding (eql 'register-plus
))
1558 (declare (ignore template instr env
))
1559 (with-slots (register)
1561 (and (ecase operand-type
1562 ((+r8
) (member register
'(al cl dl bl ah ch dh bh
)))
1563 ((+r16
) (member register
'(ax cx dx bx sp bp si di
)))
1564 ((+r32
) (member register
'(eax ecx edx ebx esp ebp esi edi
))))
1567 (defmethod operand-decode ((operand operand-register
)
1568 (encoding (eql 'register-plus
))
1570 (with-slots (register)
1573 (decode-set (find-register-decode-set (operand-class-register-set (class-of operand
)))
1575 (slot-value instr-symbolic
'opcode
)))))
1578 (defmethod operand-encode ((operand operand-register
)
1579 (encoding (eql 'register-plus
))
1582 (with-slots (opcode)
1584 (setf (ldb (byte 3 0) opcode
)
1585 (decode-set (find-register-encode-set operand-type
)
1586 (slot-value operand
'register
))))
1587 (values instr-symbolic
'(opcode)))
1590 ;;; Immediate values
1592 (def-operand-class (immediate (imm8 simm8 imm16 simm32 imm32
)) (operand-immediate) ())
1594 (defmethod operand-and-encoding-unify ((operand operand-immediate
)
1595 (encoding (eql 'immediate
))
1599 (declare (ignore template instr env
))
1602 (and (ecase operand-type
1603 (simm8 (<= #x-80 value
#x7f
))
1604 (imm8 (<= 0 value
#xff
))
1605 (imm16 (<= 0 value
#xffff
))
1606 (simm32 (<= #x-80000000 value
#xffffffff
))
1607 (imm32 (<= 0 value
#xffffffff
)))
1610 (defmethod operand-and-encoding-unify ((operand abstract-operand
)
1611 (encoding (eql 'immediate
))
1615 (operand-and-encoding-unify (make-instance 'operand-immediate
1616 'value
(operand-resolve-to-number operand env
))
1617 encoding operand-type
1618 template instr env
))
1620 (defmethod operand-decode ((operand operand-immediate
)
1621 (encoding (eql 'immediate
))
1625 (setf value
(sign-extend (realpart (slot-value instr-symbolic
'immediate
))
1626 (imagpart (slot-value instr-symbolic
'immediate
)))))
1629 (defmethod operand-encode ((operand operand-immediate
)
1630 (encoding (eql 'immediate
))
1633 (declare (ignore operand-type
))
1634 (unless (instr-symbolic-reg instr-symbolic
)
1635 (setf (instr-symbolic-reg instr-symbolic
) 0)) ; don't care)
1636 (with-slots (immediate)
1638 (setf immediate
(slot-value operand
'value
)))
1639 (values instr-symbolic
'(immediate)))
1641 ;;; PC-relative addresses
1643 (def-operand-class (pc-relative (rel8 rel16 rel32
)) (operand-rel-pointer) ())
1645 (defmethod operand-and-encoding-unify ((operand operand-rel-pointer
)
1646 (encoding (eql 'pc-relative
))
1650 (declare (ignore template instr env
))
1651 (with-slots (offset)
1653 (and (ecase operand-type
1654 ((rel8) (<= #x-80 offset
#x7f
))
1655 ((rel16) (<= #x-8000 offset
#x7fff
))
1656 ((rel32) (<= #x-80000000 offset
#x7fffffff
)))
1659 (defmethod operand-and-encoding-unify ((operand abstract-operand
)
1660 (encoding (eql 'pc-relative
))
1666 (operand-and-encoding-unify (make-instance 'operand-rel-pointer
1667 'offset
(abstract-operand-to-offset operand
1671 encoding operand-type
1672 template instr env
))
1674 ;; rel16 operands cause EIP to be masked with #x0000ffff
1675 (and (<= 0 (operand-resolve-to-number operand env
) #x0000ffff
)
1676 (operand-and-encoding-unify (make-instance 'operand-rel-pointer
1677 'offset
(abstract-operand-to-offset operand
1681 encoding operand-type
1682 template instr env
)))))
1684 (defmethod operand-decode ((operand operand-rel-pointer
)
1685 (encoding (eql 'pc-relative
))
1687 (with-slots (offset)
1690 (realpart (slot-value instr-symbolic
'displacement
))))
1693 (defmethod operand-encode ((operand operand-rel-pointer
)
1694 (encoding (eql 'pc-relative
))
1697 (declare (ignore operand-type
))
1698 (with-slots (displacement)
1701 (slot-value operand
'offset
)))
1702 (values instr-symbolic
'(displacement)))
1704 ;;; 32-bit Segmented addresses
1706 (def-operand-class (ptr16-32 (ptr16-32)) (operand-direct) ())
1708 (defmethod operand-and-encoding-unify ((operand operand-direct
)
1709 (encoding (eql 'ptr16-32
))
1713 (declare (ignore template instr
))
1714 (assert (eq operand-type
'ptr16-32
))
1715 (let ((resolved-operand (resolve-direct operand env
)))
1716 (with-slots (address segment
)
1719 (<= 0 address
#xffffffff
)
1721 (<= 0 segment
#xffff
)
1722 resolved-operand
))))
1724 (defmethod operand-decode ((operand operand-direct
)
1725 (encoding (eql 'ptr16-32
))
1727 (with-slots (address segment
)
1730 address
(ldb (byte 32 0) (realpart (instr-symbolic-displacement instr-symbolic
)))
1731 segment
(ldb (byte 16 32) (realpart (instr-symbolic-displacement instr-symbolic
)))))
1734 (defmethod operand-encode ((operand operand-direct
)
1735 (encoding (eql 'ptr16-32
))
1738 (declare (ignore operand-type
))
1739 (with-slots (displacement)
1742 (ldb (byte 32 0) displacement
) (slot-value operand
'address
)
1743 (ldb (byte 16 32) displacement
) (slot-value operand
'segment
)))
1744 (values instr-symbolic
'(displacement)))
1746 ;;; 16-bit Segmented addresses
1748 (def-operand-class (ptr16-16 (ptr16-16)) (operand-direct) ())
1750 (defmethod operand-and-encoding-unify ((operand operand-direct
)
1751 (encoding (eql 'ptr16-16
))
1755 (declare (ignore template instr
))
1756 (assert (eq operand-type
'ptr16-16
))
1757 (let ((resolved-operand (resolve-direct operand env
)))
1758 (with-slots (address segment
)
1761 (<= 0 address
#xffff
)
1763 (<= 0 segment
#xffff
)
1764 resolved-operand
))))
1766 (defmethod operand-decode ((operand operand-direct
)
1767 (encoding (eql 'ptr16-16
))
1769 (with-slots (address segment
)
1772 address
(ldb (byte 16 0) (realpart (instr-symbolic-displacement instr-symbolic
)))
1773 segment
(ldb (byte 16 16) (realpart (instr-symbolic-displacement instr-symbolic
)))))
1776 (defmethod operand-encode ((operand operand-direct
)
1777 (encoding (eql 'ptr16-16
))
1780 (declare (ignore operand-type
))
1781 (with-slots (displacement)
1783 (setf displacement
0
1784 (ldb (byte 16 0) displacement
) (slot-value operand
'address
)
1785 (ldb (byte 16 16) displacement
) (slot-value operand
'segment
)))
1786 (values instr-symbolic
'(displacement)))
1788 ;;; Two immediate operands (for ENTER)
1790 (def-operand-class (imm16-8 (imm16-8)) (operand-immediate) ())
1792 (defmethod operand-and-encoding-unify ((operand operand-immediate
)
1793 (encoding (eql 'imm16-8
))
1797 (declare (ignore template instr env
))
1798 (assert (eq operand-type
'imm16-8
))
1801 (and (<= 0 value
#xffff
)
1804 (defmethod operand-decode ((operand operand-immediate
)
1805 (encoding (eql 'imm16-8
))
1809 (setf value
(ldb (byte 16 0)
1810 (realpart (slot-value instr-symbolic
'immediate
)))))
1813 (defmethod operand-encode ((operand operand-immediate
)
1814 (encoding (eql 'imm16-8
))
1817 (assert (eq operand-type
'imm16-8
)
1819 (unless (instr-symbolic-immediate instr-symbolic
)
1820 (setf (slot-value instr-symbolic
'immediate
) 0))
1821 (with-slots (immediate)
1823 (setf (ldb (byte 16 0) immediate
)
1824 (slot-value operand
'value
)))
1825 (values instr-symbolic
'(immediate)))
1828 ;;; Two immediate operands (for ENTER)
1830 (def-operand-class (imm8-0 (imm8-0)) (operand-immediate) ())
1832 (defmethod operand-and-encoding-unify ((operand operand-immediate
)
1833 (encoding (eql 'imm8-0
))
1837 (declare (ignore template instr env
))
1838 (assert (eq operand-type
'imm8-0
))
1841 (and (<= 0 value
#x7f
)
1844 (defmethod operand-decode ((operand operand-immediate
)
1845 (encoding (eql 'imm8-0
))
1849 (setf value
(ldb (byte 8 16)
1850 (realpart (slot-value instr-symbolic
'immediate
)))))
1853 (defmethod operand-encode ((operand operand-immediate
)
1854 (encoding (eql 'imm8-0
))
1857 (assert (eq operand-type
'imm8-0
)
1859 (unless (instr-symbolic-immediate instr-symbolic
)
1860 (setf (slot-value instr-symbolic
'immediate
) 0))
1861 (with-slots (immediate)
1863 (setf (ldb (byte 8 16) immediate
)
1864 (slot-value operand
'value
)))
1865 (values instr-symbolic
'(immediate)))