2 (in-package :cl-x86-asm
)
4 ;; -- instruction encoding -----------------------------------------------------
6 (defun encode-32-bit-register-address (ea instruction
)
7 "(ecode-32-bit-register-address ea instruction) Handle the case in
8 which our ea is just a register"
11 (|r
/m|
(or (byte-register ea
)
14 (get-mod-rm-field :spare
16 (get instruction
:|mod-rm|
)))))
17 (setf (get instruction
:|mod-r
/m|
)
18 (make-mod-rm-byte mod |r
/m| spare
))))
21 (defun encode-32-bit-memory-address (ea instruction
)
22 "(ecode-32-bit-register-address ea instruction) Handle the case in
23 which our ea is not a register but some indirect formulation of
24 base, index, scale, displacement etc.."
25 (with-effective-address
26 (size segment-reg base-reg scale index-reg
27 displacement immediate
)
30 ((displacement-only-p ()
31 (and (not (zerop displacement
))
35 (base-and-displacement-only-p ()
36 (and (not (zerop displacement
))
42 ((displacement-only-p) 0)
43 ((zerop displacement
) 0)
44 ((is-byte displacement
) 1)
45 ((is-dword displacement
) 2)
47 (error "Displacement ~X out of range"
51 ((displacement-only-p) 5)
52 ((not (base-and-displacement-only-p)) 4)
53 (t (byte-register base-reg
)
54 (dword-register base-reg
)))))
59 (when (and (not (displacement-only-p))
60 (not (base-and-displacement-only-p)))
61 (or (byte-register base-reg
)
62 (dword-register base-reg
))))
64 (when (and (not (displacement-only-p))
65 (not (base-and-displacement-only-p)))
66 (or (byte-register index-reg
)
67 (dword-register index-reg
))))
76 (setf (get instruction
:|mod-r
/m|
)
77 (make-mod-rm-byte mod |r
/m|
0))
78 (setf (get instruction
:sib
)
79 (make-sib-byte scale index base
))
82 (defun encode-16-bit-ea (instruction)
83 (declare (ignore instruction
))
84 (error "Cannot handle 16 bit addressing yet"))
86 ;; to do -- what about 16 bits and segment displacement and word sizes?
87 (defun encode-effective-address (operand instruction
)
88 (ccase *current-bits-size
*
89 ;; In 32-bit addressing mode ..
90 ;; (either BITS 16 with a 67 prefix, or BITS 32 with no 67 prefix)
91 ;; the general rules (again, there are exceptions) for mod and r/m are:
94 ((or (byte-register operand
)
95 (dword-register operand
))
96 (encode-32-bit-register-address operand instruction
))
97 ((word-register operand
)
98 (error "Can't handle word registers in 32 bit mode yet"))
101 (assert (listp operand
))
102 (encode-32-bit-memory-address operand instruction
)))))
104 (16 (encode-16-bit-ea instruction
))))
106 ;; -- encoding method lookup table ---------------------------------------------------
108 (defparameter *opcode-encodings
* '(:|rw
/rd|
:|rb|
:|ow
/od|
:OF
:/2 :|
+cc|
109 :/7 :/3 :/1 :/4 :/5 :/0 :|
+r|
:/6 :|ib|
110 :|iw|
:|o16|
:|id|
:|o32|
:|
/r|
))
112 (defparameter *opcode-encoder-table
* (make-hash-table))
114 (defun def-opcode-encoder (encoding function
)
115 (assert (member encoding
*opcode-encodings
*))
116 (setf (gethash encoding
*opcode-encoder-table
*) function
))
118 (defun find-operand-index (types valid-types
)
119 "(find-operand-types types valid-types) types is a list of
120 operand types in operand order, and valid-types is a list of
121 operand types allowed for a given encoding. Returns the index of
122 the operand we need to encode."
124 for operand-index
= 0 then
(1+ operand-index
)
125 for operand-type in types
126 thereis
(and (member operand-type valid-types
)
129 ;; :|+r| - one of the operands is a register and the register value
130 ;; should be added to the appropiate opcode to produce the byte
131 (defun register-opcode-encoder (insn-name operands types encoding instruction
)
132 "(register-opcode-endoder isnn-name operands types ecoding instruction) Handles
133 the effect of a :|+r| encoding on an instruction."
134 (declare (ignore insn-name
))
135 (assert (eql (first (last encoding
)) :|
+r|
))
136 (flet ((add-register-value-to-opcodes (opcodes reg-value
)
138 (subseq opcodes
0 (1- (length opcodes
)))
139 (list (+ reg-value
(nth (1- (length opcodes
)) opcodes
))))))
140 (let* ((register-types '(:|reg32|
:|reg16|
:|reg8|
))
141 (operand-index (find-operand-index types register-types
))
142 (register-value (or (byte-register (nth operand-index operands
))
143 (word-register (nth operand-index operands
))
144 (dword-register (nth operand-index operands
))))
145 (opcodes (get instruction
:opcodes
)))
146 (when (null operand-index
)
147 (error "Unable to identify operand to encode among ~A " operands
))
148 (setf (get instruction
:opcodes
)
149 (add-register-value-to-opcodes opcodes register-value
)))))
151 ;; :|+cc| condition code should be added to opcode byte - placeholder
152 ;; that does nothing as this was expanded manually in our instruction table
153 (defun condition-code-opcode-encoder (insn-name operands types encoding instruction
)
154 (declare (ignore insn-name operands types encoding
))
157 (defmacro def-slash-opcode-encoder
(n &key name
)
158 `(defun ,name
(insn-name operands types encoding instruction
)
159 (declare (ignore insn-name encoding
))
161 '(:|mm|
:|m80|
:|m8|
:|mem80|
:|mem64|
:|mem32|
:|mem16|
:|mem8|
162 :|mem|
:|r
/m8|
:|r
/m16|
:|r
/m32|
:|xmm2
/m128|
))
163 (operand-index (find-operand-index types ea-types
))
164 (mod-rm (zero-when-null (get instruction
:|mod-r
/m|
))))
165 (when (not (numberp operand-index
))
167 "Unable to identify operand to encode among ~A " operands
))
168 (encode-effective-address (nth operand-index operands
) instruction
)
169 (setf (get instruction
:|mod-r
/m|
)
171 (get-mod-rm-field :mod mod-rm
)
173 (get-mod-rm-field :|r
/m| mod-rm
))))))
175 (def-slash-opcode-encoder 0 :name slash-zero-opcode-encoder
)
176 (def-slash-opcode-encoder 1 :name slash-one-opcode-encoder
)
177 (def-slash-opcode-encoder 2 :name slash-two-opcode-encoder
)
178 (def-slash-opcode-encoder 3 :name slash-three-opcode-encoder
)
179 (def-slash-opcode-encoder 4 :name slash-four-opcode-encoder
)
180 (def-slash-opcode-encoder 5 :name slash-five-opcode-encoder
)
181 (def-slash-opcode-encoder 6 :name slash-six-opcode-encoder
)
182 (def-slash-opcode-encoder 7 :name slash-seven-opcode-encoder
)
184 (defun slash-r-opcode-encoder (insn-name operands types encoding instruction
)
185 (declare (ignore insn-name encoding
))
186 (let* ((register-types
187 '(:|xmm1|
:|mm1|
:|reg32|
:|reg16|
:|reg8|
:|mmxreg|
:|xmm|
:|mm|
))
189 '(:|mm|
:|m80|
:|m8|
:|mem80|
:|mem64|
:|mem32|
:|mem16|
:|mem8|
190 :|mem|
:|r
/m8|
:|r
/m16|
:|r
/m32|
:|xmm2
/m128|
))
191 (register-operand-index
192 (find-operand-index types register-types
))
194 (find-operand-index types ea-types
))
197 (nth register-operand-index operands
))
199 (nth register-operand-index operands
))))
200 (mod-rm (zero-when-null (get instruction
:|mod-r
/m|
))))
201 (when (not (and (numberp register-operand-index
) (numberp ea-operand-index
)))
203 "Unable to identify operand to encode among ~A " operands
))
204 (when (not (numberp register-value
))
206 "Unable to encode register ~A " (nth register-operand-index operands
)))
207 (encode-effective-address (nth ea-operand-index operands
) instruction
)
208 (setf (get instruction
:|mod-r
/m|
)
210 (get-mod-rm-field :mod mod-rm
)
212 (get-mod-rm-field :|r
/m| mod-rm
)))))
214 (defun o32-opcode-encoder (insn-name operands
215 types encoding instruction
)
216 (declare (ignore insn-name operands types
))
217 (when (member :|o32| encoding
)
218 (when (= *current-bits-size
* 16)
219 (setf (get instruction
:prefix
)
220 (list +OPERAND-SIZE-OVERRIDE-PREFIX
+)))))
222 (defun o16-opcode-encoder (insn-name operands
223 types encoding instruction
)
224 (declare (ignore insn-name operands types
))
225 (when (member :|o16| encoding
)
226 (when (= *current-bits-size
* 32)
227 (setf (get instruction
:prefix
)
228 (list +OPERAND-SIZE-OVERRIDE-PREFIX
+)))))
230 ;; to do -- must understand symbols
231 (defun ib-opcode-encoder (insn-name operands
232 types encoding instruction
)
233 (declare (ignore insn-name type encoding
))
234 (let ((operand-index (find-operand-index types
'(:|imm8|
))))
235 (assert (not (null operand-index
)))
236 (setf (get instruction
:immediate-data
)
237 (decompose-to-n-bytes
238 (nth operand-index operands
) 1))))
240 ;; to do -- must understand symbols
241 (defun iw-opcode-encoder (insn-name operands
242 types encoding instruction
)
243 (declare (ignore insn-name type encoding
))
245 (find-operand-index types
'(:|imm16|
))))
246 (assert (not (null operand-index
)))
247 (setf (get instruction
:immediate-data
)
248 (decompose-to-n-bytes
249 (nth operand-index operands
) 2))))
251 ;; to do -- must understand symbols
252 (defun id-opcode-encoder (insn-name operands
253 types encoding instruction
)
254 (declare (ignore insn-name type encoding
))
256 (find-operand-index types
'(:|imm32|
))))
257 (assert (not (null operand-index
)))
258 (setf (get instruction
:immediate-data
)
259 (decompose-to-n-bytes
260 (nth operand-index operands
) 4))))
264 ;; # The codes rb, rw and rd indicate that one of the operands
265 ;; to the instruction is an immediate value, and that the difference
266 ;; between this value and the address of the end of the instruction is
267 ;; to be encoded as a byte, word or doubleword respectively. Where the
268 ;; form rw/rd appears, it indicates that either rw or rd should be
269 ;; used according to whether assembly is being performed in BITS 16 or
270 ;; BITS 32 state respectively.
272 ;; # The codes ow and od indicate that one of the operands to the
273 ;; # instruction is a reference to the contents of a memory address
274 ;; # specified as an immediate value: this encoding is used in some
275 ;; # forms of the MOV instruction in place of the standard
276 ;; # effective-address mechanism. The displacement is encoded as a
277 ;; # word or doubleword. Again, ow/od denotes that ow or od should be
278 ;; # chosen according to the BITS setting.
280 ;; # The codes o16 and o32 indicate that the given form of the
281 ;; # instruction should be assembled with operand size 16 or 32
282 ;; # bits. In other words, o16 indicates a 66 prefix in BITS 32 state,
283 ;; # but generates no code in BITS 16 state; and o32 indicates a 66
284 ;; # prefix in BITS 16 state but generates nothing in BITS 32.
286 ;; # The codes a16 and a32, similarly to o16 and o32, indicate the
287 ;; # address size of the given form of the instruction. Where this
288 ;; # does not match the BITS setting, a 67 prefix is required.
290 (def-opcode-encoder :|
+r|
#'register-opcode-encoder
)
291 (def-opcode-encoder :|
+cc|
#'condition-code-opcode-encoder
)
292 (def-opcode-encoder :/0 #'slash-zero-opcode-encoder
)
293 (def-opcode-encoder :/1 #'slash-one-opcode-encoder
)
294 (def-opcode-encoder :/2 #'slash-two-opcode-encoder
)
295 (def-opcode-encoder :/3 #'slash-three-opcode-encoder
)
296 (def-opcode-encoder :/4 #'slash-four-opcode-encoder
)
297 (def-opcode-encoder :/5 #'slash-five-opcode-encoder
)
298 (def-opcode-encoder :/6 #'slash-six-opcode-encoder
)
299 (def-opcode-encoder :/7 #'slash-seven-opcode-encoder
)
300 (def-opcode-encoder :|
/r|
#'slash-r-opcode-encoder
)
301 (def-opcode-encoder :|ib|
#'ib-opcode-encoder
)
302 (def-opcode-encoder :|iw|
#'iw-opcode-encoder
)
303 (def-opcode-encoder :|id|
#'id-opcode-encoder
)
304 (def-opcode-encoder :|o32|
#'o32-opcode-encoder
)
305 (def-opcode-encoder :|o16|
#'o16-opcode-encoder
)