Modified:
trunk/cc/lap.lisp
trunk/cc/test-cc.lisp
trunk/cc/x86-64-syntax.lisp
wiki/AssemblyX64C.wiki
wiki/AssemblyX64Overview.wiki
Log:
Add instruction cmovcc.
Modified: trunk/cc/lap.lisp
==============================================================================
--- trunk/cc/lap.lisp (original)
+++ trunk/cc/lap.lisp Tue Feb 24 06:22:50 2009
@@ -102,7 +102,7 @@
(pp-hex (read-image filename)))
(defparameter *prefix-mapping*
- `((lock . #xf0)
+ `((lock . #xf0)
(repne . #xf2) (repnz .#xf2)
(rep . #xf3) (repe . #xf3) (repz . #xf3))
"Prefix mapping table.")
@@ -142,6 +142,14 @@
(member (car (last x)) '(1 cl)))))
;; Special case for (shl/shr r/m8/16 1/cl).
(encode-complex (butlast e) (butlast (instruction-type e)) it cursor
bits))
+ ((and (>= (length (str (car e))) 5) (string= (subseq (str (car e)) 0
4) "CMOV")
+ (>= (cc->int (symb (subseq (str (car e)) 4))) 0))
+ ;; CMOVcc.
+ (declare (ignore it))
+ (let* ((cc (symb (subseq (str (car e)) 4)))
+ (cc-code (cc->int cc))
+ (e* (cons 'cmovcc (cdr e))))
+ (match-n-encode e* cursor bits cc-code)))
(t
(declare (ignore it))
(case (car e)
@@ -160,13 +168,13 @@
;; Normal instructions.
(t (match-n-encode e cursor bits))))))
-(defun match-n-encode (e cursor bits)
+(defun match-n-encode (e cursor bits &optional (cc-code 0))
"Match instruction and encode it."
(multiple-value-bind (type opcode)
(match-instruction e (instruction-type e) bits)
- (encode-complex e type opcode cursor bits)))
+ (encode-complex e type opcode cursor bits cc-code)))
-(defun encode-complex (instruction type opcode cursor bits)
+(defun encode-complex (instruction type opcode cursor bits &optional
(cc-code 0))
"Encode instruction (with optional rex prefix). Other prefixes like
lock are directly handled in encode()."
(let* (rex-set ; Possibly containing a subset of {w r x b}.
@@ -181,7 +189,8 @@
(ecase (car on)
(+ (ecase (caddr on)
(r (list (+ (cadr on)
- (reg->int (second instruction)))))))))
+ (reg->int (second instruction)))))
+ (cc (list (+ (cadr on) cc-code)))))))
(t
(ecase on
((o16 o32 a16 a32) (size-prefix on bits))
@@ -279,7 +288,7 @@
Note
1. If sib is not needed, return nil.
2. If disp is not needed, return nil as disp and disp-length
- could be arbitrary."
+ could be arbitrary."
(ecase (operand-type r/m)
((r8 r16 r32 r64)
(multiple-value-bind (regi rex)
@@ -592,6 +601,16 @@
(ds 3)
(fs 4)
(gs 5)))
+
+(defun cc->int (cc)
+ "Returns the integer representing conditional codes (cc) used by
+cmovcc and jcc. Returns -1 if cc is not a valid value."
+ (case cc
+ (o 0) (no 1) ((b c nae) 2) ((ae nb nc) 3)
+ ((e z) 4) ((ne nz) 5) ((be na) 6) ((a nbe) 7)
+ (s 8) (ns 9) ((p pe) 10) ((np po) 11)
+ ((l nge) 12) ((ge nl) 13) ((le ng) 14) ((g nle) 15)
+ (t -1)))
(defun string->bytes (s)
(map 'list #'char-code s))
Modified: trunk/cc/test-cc.lisp
==============================================================================
--- trunk/cc/test-cc.lisp (original)
+++ trunk/cc/test-cc.lisp Tue Feb 24 06:22:50 2009
@@ -210,6 +210,9 @@
(stosw)
(bits 64)
+ (cmova ax bx)
+ (cmovc eax edx)
+ (cmove rdx r10)
(syscall)
(sysret)
@@ -224,13 +227,14 @@
"Miscellaneous instructions.")
(defparameter *misc-code*
- '(232 97 0 248 252 250 244 228 3 229 4 236 237 204 205 16 235 254 15
- 1 22 100 124 15 1 30 100 124 15 0 210 15 0 22 100 124 172 173 226
- 232 180 9 187 13 0 137 200 137 30 100 124 139 14 123 28 199 6 100
- 124 123 0 142 195 140 200 144 230 3 231 4 238 239 81 14 22 30 6 90
- 23 31 7 243 164 243 165 243 102 165 195 249 253 251 170 171 15 5
- 15 7 100 124 72 101 108 108 111 32 87 111 114 108 100 33 32 0 0 0
- 85 170 64 226 1 0 67 104 120 0 0 0 230 130 217 250 11 0))
+ '(232 108 0 248 252 250 244 228 3 229 4 236 237 204 205 16 235 254
+ 15 1 22 111 124 15 1 30 111 124 15 0 210 15 0 22 111 124 172 173
+ 226 232 180 9 187 13 0 137 200 137 30 111 124 139 14 123 28 199 6
+ 111 124 123 0 142 195 140 200 144 230 3 231 4 238 239 81 14 22 30
+ 6 90 23 31 7 243 164 243 165 243 102 165 195 249 253 251 170 171
+ 102 15 71 195 15 66 194 73 15 68 210 15 5 15 7 111 124 72 101 108
+ 108 111 32 87 111 114 108 100 33 32 0 0 0 85 170 64 226 1 0 67 104
+ 120 0 0 0 230 130 217 250 11 0))
(defparameter *address-asm*
'((org #x7c00)
Modified: trunk/cc/x86-64-syntax.lisp
==============================================================================
--- trunk/cc/x86-64-syntax.lisp (original)
+++ trunk/cc/x86-64-syntax.lisp Tue Feb 24 06:22:50 2009
@@ -10,7 +10,8 @@
(in-package :cc)
(defun arith-syntax-1 (mnemonic 64bit-only?)
- "Return syntax table for arithmetic operations: add/and/cmp/or/sub/xor."
+ "Return syntax table for arithmetic operations:
+adc/add/and/cmp/or/sbb/sub/xor."
(let ((base ; Base opcode for operation on r/m8 r8.
(ecase mnemonic
(adc #x10) (add #x00) (and #x20) (cmp #x38)
@@ -92,6 +93,8 @@
((clc) . (#xf8))
((cld) . (#xfc))
((cli) . (#xfa))
+ ((cmovcc r16 (r/m16 r16 m)) . (o16 #x0f (+ #x40 cc) /r))
+ ((cmovcc r32 (r/m32 r32 m)) . (o32 #x0f (+ #x40 cc) /r))
,@(arith-syntax-1 'cmp nil)
((dec (r/m8 r8)) . (#xfe /1))
((dec byte m) . (#xfe /1))
@@ -185,6 +188,7 @@
`(,@(arith-syntax-1 'adc t)
,@(arith-syntax-1 'add t)
,@(arith-syntax-1 'and t)
+ ((cmovcc r64 (r/m64 r64 m)) . (#x0f (+ #x40 cc) /r))
,@(arith-syntax-1 'cmp t)
((dec (r/m64 r64)) . (#xff /1))
((dec qword m) . (#xff /1))
Modified: wiki/AssemblyX64C.wiki
==============================================================================
--- wiki/AssemblyX64C.wiki (original)
+++ wiki/AssemblyX64C.wiki Tue Feb 24 06:22:50 2009
@@ -27,6 +27,15 @@
--------
+= cmov: Conditional Move =
+
+|| Instruction || Opcode || 64-Bit Mode || 16/32-Bit Mode
|| Description ||
+|| cmov r16 r/m16 || o16 0F (+ 40 cc) /r || Valid || Valid
|| ||
+|| cmov r32 r/m32 || o32 0F (+ 40 cc) /r || Valid || Valid
|| ||
+|| cmov r64 r/m64 || 0F (+ 40 cc) /r || Valid || ~~N.E.~~
|| ||
+
+Please refer [AssemblyX64Overview#Conditional_Codes conditional codes] for
details.
+
= cmp: Compare =
|| Instruction || Opcode || 64-Bit Mode || 16/32-Bit Mode ||
Description ||
Modified: wiki/AssemblyX64Overview.wiki
==============================================================================
--- wiki/AssemblyX64Overview.wiki (original)
+++ wiki/AssemblyX64Overview.wiki Tue Feb 24 06:22:50 2009
@@ -26,32 +26,32 @@
* *Valid*: supported.
* *Invalid*: not supported.
* *N.E.*: not encodable. The opcode may be part of a sequence of other
-valid instructions.
+ valid instructions.
* *N.S.*: not supported. The instruction requires an address override
prefix.
= Notations for Instructions =
-
+
Following notations are used:
* *imm8*: immediate byte value in the range of -128..+255.
* *imm16*: immediate word value in the range of -32,768..+65,535.
* *imm32*: immediate doubleword value in the range of
--2,147,483,648..+4,294,967,295.
+ -2,147,483,648..+4,294,967,295.
* *imm64*: immediate quadword value in the range of
--9,223,372,036,854,775,808..+18,446,744,073,709,551,615..
+ -9,223,372,036,854,775,808..+18,446,744,073,709,551,615..
* *!r8*: one of the byte general-purpose registers: al, cl, dl, bl, ah,
ch,
-dh, bh, bpl, spl, dil, and sil.
+ dh, bh, bpl, spl, dil, and sil.
* *!r16*: one of the word general-purpose registers: ax, cx, dx, bx, sp,
bp,
-si, di.
+ si, di.
* *!r32*: one of the doubleword general-purpose registers: eax, ecx, edx,
ebx,
-esp, ebp, esi, edi.
+ esp, ebp, esi, edi.
* *!r64*: one of the quadword general-purpose registers: rax, rcx, rdx,
rbx,
-rsp, rbp, rsi, rdi, !r8-!r15.
+ rsp, rbp, rsi, rdi, !r8-!r15.
* *m8, m16, m32, m64*: memory references. Specifier (`byte`, `word`,
`dword`, `qword`)
-is needed for ambiguous cases. For example in `(mov word [12345] 16).
+ is needed for ambiguous cases. For example in `(mov word [12345] 16).
* *m16&32*, *m16&16*, *m32&32*, *m16&64*, a memory operand containing one
pair whose sizes
-are indicated on the left and right size of the ampersand.
+ are indicated on the left and right size of the ampersand.
* *r/m8, r/m16, r/m32, r/m64*: register or memeory choices. For example,
r/m8
-means that either r8 or m8 can be used as operand.
+ means that either r8 or m8 can be used as operand.
* *sreg*: segment register.
== Range of Immediate Values ==
@@ -75,28 +75,50 @@
Following notations are used:
* A hex number, such as CC, indicates a fixed byte containing that number.
* A hex number followed by *+r*, like *B0+r*, indicates that one of the
operands
-is a register, and correspondign register value should be added to the
opcode.
+ is a register, and correspondign register value should be added to the
opcode.
* */n* (where n is 0 to 7): indictes that one of the operand is r/m, and
the field
-Reg/Opcode should be encoded with n.
+ Reg/Opcode should be encoded with n.
* */r*: ModR/M byte of the instruction contains a register operand
(encoded in
-field Reg/Opcode) and an r/m operand (encoded in field R/M).
+ field Reg/Opcode) and an r/m operand (encoded in field R/M).
* *rb, rw, rd, ro*: one of the operands is an immediate value, and the
-_difference_ between this value and the end address of the instruction is
-to be encoded as byte (rb), little-endian word (rw), little-endian
+ _difference_ between this value and the end address of the instruction
is
+ to be encoded as byte (rb), little-endian word (rw), little-endian
doubleword (rd), and little-endian quadword (ro) respectively.
* *ib, iw, id, io*: one of the operands is an immediate value, and it is
to be
-encoded as byte (rb), little-endian word (rw), little-endian doubleword
(rd),
-and little-endian quadword (ro) respectively.
-* *o16, o32*: operand-size override prefix. o16 generates no code in
-16-bit mode, but indicates a 66h prefix in 32/64-bit mode; similarly, o32
generates
-no code in 32/64-bit mode, but indicates a 66h prefix in 16-bit mode.
-* *a16, a32*: address-size override prefix. a16 generates no code in
-16-bit mode, but indicates a 67h prefix in 32/64-bit mode; similarly, a32
generates
-no code in 32/64-bit mode, but indicates a 67h prefix in 16-bit mode.
+ encoded as byte (rb), little-endian word (rw), little-endian doubleword
(rd),
+ and little-endian quadword (ro) respectively.
+ * *o16, o32*: operand-size override prefix. o16 generates no code in
+ 16-bit mode, but indicates a 66h prefix in 32/64-bit mode; similarly,
o32 generates
+ no code in 32/64-bit mode, but indicates a 66h prefix in 16-bit mode.
+ * *a16, a32*: address-size override prefix. a16 generates no code in
+ 16-bit mode, but indicates a 67h prefix in 32/64-bit mode; similarly,
a32 generates
+ no code in 32/64-bit mode, but indicates a 67h prefix in 16-bit mode.
Note that REX prefix are not used in opcode notations. The prefix is
automatically generated by analyzing the operands.
-
+== Conditional Codes ==
+
+Conditional codes are used for Jcc and CMOVcc instructions, which are
+encoded as (+ xx cc). Meaning of conditional codes are listed below.
+|| cc || value || trigger
flag ||
+|| o || 0 || overflow flag
set ||
+|| no || 1 || overflow flag not
set ||
+|| b c nae || 2 || carry flag
set ||
+|| ae nb nc || 3 || carry flag not
set ||
+|| e z || 4 || zero flag
set ||
+|| ne nz || 5 || zero flag not
set ||
+|| be na || 6 || either of carry or zero flag
set ||
+|| a nbe || 7 || neither carry nor zero flag
set ||
+|| s || 8 || sign flag
set ||
+|| ns || 9 || sign flag not
set ||
+|| p pe || 10 || parity flag
set ||
+|| np po || 11 || parity flag not
set ||
+|| l nge || 12 || exactly one of sign and overflow flag is
set ||
+|| ge nl || 13 || opposite case of
above ||
+|| le ng || 14 || either the zero flag is set, or exactly one of
sign and overflow flag is set ||
+|| g nle || 15 || opposite case of
above ||
+
+