* x86expr.c (yasm_x86__expr_checkea): Add address16_op parameter to avoid

errors when using enter in 64-bit mode.
* x86arch.h (yasm_x86__expr_checkea): Update prototype.
* x86bc.c (x86_bc_insn_resolve, x86_bc_insn_tobytes): Pass flag to above.

* x86id.re: Implement mul, imul, div, idiv, enter, leave for GAS mode.
Add tests for above.

svn path=/trunk/yasm/; revision=1245
0.5.0rc2
Peter Johnson 20 years ago
parent 017d66ed0b
commit 68f8b061c3
  1. 9
      modules/arch/x86/tests/gas64/Makefile.inc
  2. 36
      modules/arch/x86/tests/gas64/gas-muldiv.asm
  3. 0
      modules/arch/x86/tests/gas64/gas-muldiv.errwarn
  4. 624
      modules/arch/x86/tests/gas64/gas-muldiv.hex
  5. 16
      modules/arch/x86/tests/gas64/gas-retenter.asm
  6. 0
      modules/arch/x86/tests/gas64/gas-retenter.errwarn
  7. 528
      modules/arch/x86/tests/gas64/gas-retenter.hex
  8. 26
      modules/arch/x86/tests/gas64/gas-shift.asm
  9. 0
      modules/arch/x86/tests/gas64/gas-shift.errwarn
  10. 576
      modules/arch/x86/tests/gas64/gas-shift.hex
  11. 9
      modules/arch/x86/x86arch.h
  12. 11
      modules/arch/x86/x86bc.c
  13. 14
      modules/arch/x86/x86expr.c
  14. 230
      modules/arch/x86/x86id.re

@ -12,6 +12,15 @@ EXTRA_DIST += modules/arch/x86/tests/gas64/gas-inout.hex
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-movsxs.asm
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-movsxs.errwarn
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-movsxs.hex
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-muldiv.asm
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-muldiv.errwarn
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-muldiv.hex
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-retenter.asm
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-retenter.errwarn
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-retenter.hex
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-shift.asm
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-shift.errwarn
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-shift.hex
EXTRA_DIST += modules/arch/x86/tests/gas64/riprel.asm
EXTRA_DIST += modules/arch/x86/tests/gas64/riprel.errwarn
EXTRA_DIST += modules/arch/x86/tests/gas64/riprel.hex

@ -0,0 +1,36 @@
mulb %bl
mulw %bx
mull %ebx
mulq %rbx
imulw %bx, %cx
imull %ebx, %ecx
imulq %rbx, %rcx
imulw $5, %bx, %cx
imull $5, %ebx, %ecx
imulq $5, %rbx, %rcx
imulw $5000, %bx, %cx
imull $5000, %ebx, %ecx
imulq $5000, %rbx, %rcx
imulw $5, %cx
imull $5, %ecx
imulq $5, %rcx
imulw $5000, %cx
imull $5000, %ecx
imulq $5000, %rcx
divb %cl
divw %cx
divl %ecx
divq %rcx
divb %cl, %al
divw %cx, %ax
divl %ecx, %eax
divq %rcx, %rax
idivb %cl
idivw %cx
idivl %ecx
idivq %rcx
idivb %cl, %al
idivw %cx, %ax
idivl %ecx, %eax
idivq %rcx, %rax

@ -0,0 +1,624 @@
7f
45
4c
46
02
01
01
00
00
00
00
00
00
00
00
00
01
00
3e
00
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
30
01
00
00
00
00
00
00
00
00
00
00
40
00
00
00
00
00
40
00
05
00
01
00
f6
e3
66
f7
e3
f7
e3
48
f7
e3
66
0f
af
cb
0f
af
cb
48
0f
af
cb
66
6b
cb
05
6b
cb
05
48
6b
cb
05
66
69
cb
88
13
69
cb
88
13
00
00
48
69
cb
88
13
00
00
66
6b
c9
05
6b
c9
05
48
6b
c9
05
66
69
c9
88
13
69
c9
88
13
00
00
48
69
c9
88
13
00
00
f6
f1
66
f7
f1
f7
f1
48
f7
f1
f6
f1
66
f7
f1
f7
f1
48
f7
f1
f6
f9
66
f7
f9
f7
f9
48
f7
f9
f6
f9
66
f7
f9
f7
f9
48
f7
f9
00
00
2e
74
65
78
74
00
2e
73
74
72
74
61
62
00
2e
73
79
6d
74
61
62
00
2e
73
68
73
74
72
74
61
62
00
00
00
00
00
2d
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
01
00
00
00
04
00
f1
ff
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
03
00
04
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
17
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
b8
00
00
00
00
00
00
00
21
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
07
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
dc
00
00
00
00
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
0f
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
e0
00
00
00
00
00
00
00
48
00
00
00
00
00
00
00
02
00
00
00
03
00
00
00
08
00
00
00
00
00
00
00
18
00
00
00
00
00
00
00
01
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
40
00
00
00
00
00
00
00
77
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
10
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00

@ -0,0 +1,16 @@
retw
#retl
retq
retw $5
#retl $5
retq $5
lretw
#lretl
lretq $5
enterw $5000, $5
#enterl
enterq $5000, $5
leavew
#leavel
leaveq

@ -0,0 +1,528 @@
7f
45
4c
46
02
01
01
00
00
00
00
00
00
00
00
00
01
00
3e
00
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
d0
00
00
00
00
00
00
00
00
00
00
00
40
00
00
00
00
00
40
00
05
00
01
00
66
c3
c3
66
c2
05
00
c2
05
00
66
cb
ca
05
00
66
c8
88
13
05
c8
88
13
05
66
c9
c9
00
00
2e
74
65
78
74
00
2e
73
74
72
74
61
62
00
2e
73
79
6d
74
61
62
00
2e
73
68
73
74
72
74
61
62
00
00
00
00
00
2d
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
01
00
00
00
04
00
f1
ff
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
03
00
04
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
17
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
5c
00
00
00
00
00
00
00
21
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
07
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
80
00
00
00
00
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
0f
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
84
00
00
00
00
00
00
00
48
00
00
00
00
00
00
00
02
00
00
00
03
00
00
00
08
00
00
00
00
00
00
00
18
00
00
00
00
00
00
00
01
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
40
00
00
00
00
00
00
00
1b
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
10
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00

@ -0,0 +1,26 @@
shlb $1, %al
shlb $5, %al
shlb %cl, %al
shlb %al
shlw $1, %ax
shlw $5, %ax
shlw %cl, %ax
shlw %ax
shll $1, %eax
shll $5, %eax
shll %cl, %eax
shll %eax
shlq $1, %rax
shlq $5, %rax
shlq %cl, %rax
shlq %rax
shldw $5, %bx, %dx
shldw %cl, %bx, %dx
shldw %bx, %dx
shldl $5, %ebx, %edx
shldl %cl, %ebx, %edx
shldl %ebx, %edx
shldq $5, %rbx, %rdx
shldq %cl, %rbx, %rdx
shldq %rbx, %rdx

@ -0,0 +1,576 @@
7f
45
4c
46
02
01
01
00
00
00
00
00
00
00
00
00
01
00
3e
00
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
01
00
00
00
00
00
00
00
00
00
00
40
00
00
00
00
00
40
00
05
00
01
00
d0
e0
c0
e0
05
d2
e0
d0
e0
66
d1
e0
66
c1
e0
05
66
d3
e0
66
d1
e0
d1
e0
c1
e0
05
d3
e0
d1
e0
48
d1
e0
48
c1
e0
05
48
d3
e0
48
d1
e0
66
0f
a4
da
05
66
0f
a5
da
66
0f
a5
da
0f
a4
da
05
0f
a5
da
0f
a5
da
48
0f
a4
da
05
48
0f
a5
da
48
0f
a5
da
00
2e
74
65
78
74
00
2e
73
74
72
74
61
62
00
2e
73
79
6d
74
61
62
00
2e
73
68
73
74
72
74
61
62
00
00
00
00
00
2d
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
01
00
00
00
04
00
f1
ff
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
03
00
04
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
17
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
90
00
00
00
00
00
00
00
21
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
07
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
b4
00
00
00
00
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
0f
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
b8
00
00
00
00
00
00
00
48
00
00
00
00
00
00
00
02
00
00
00
03
00
00
00
08
00
00
00
00
00
00
00
18
00
00
00
00
00
00
00
01
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
40
00
00
00
00
00
00
00
50
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
10
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00

@ -252,10 +252,11 @@ void yasm_x86__ea_init(yasm_effaddr *ea, unsigned int spare,
*/
int yasm_x86__expr_checkea
(yasm_expr **ep, unsigned char *addrsize, unsigned int bits,
unsigned int nosplit, unsigned char *displen, unsigned char *modrm,
unsigned char *v_modrm, unsigned char *n_modrm, unsigned char *sib,
unsigned char *v_sib, unsigned char *n_sib, unsigned char *pcrel,
unsigned char *rex, yasm_calc_bc_dist_func calc_bc_dist);
unsigned int nosplit, int address16_op, unsigned char *displen,
unsigned char *modrm, unsigned char *v_modrm, unsigned char *n_modrm,
unsigned char *sib, unsigned char *v_sib, unsigned char *n_sib,
unsigned char *pcrel, unsigned char *rex,
yasm_calc_bc_dist_func calc_bc_dist);
void yasm_x86__parse_cpu(yasm_arch *arch, const char *cpuid,
unsigned long line);

@ -529,10 +529,10 @@ x86_bc_insn_resolve(yasm_bytecode *bc, int save,
* displacement.
*/
switch (yasm_x86__expr_checkea(&temp, &insn->common.addrsize,
insn->common.mode_bits, ea->nosplit, &displen, &eat.modrm,
&eat.valid_modrm, &eat.need_modrm, &eat.sib,
&eat.valid_sib, &eat.need_sib, &eat.pcrel, &insn->rex,
calc_bc_dist)) {
insn->common.mode_bits, ea->nosplit, insn->address16_op,
&displen, &eat.modrm, &eat.valid_modrm, &eat.need_modrm,
&eat.sib, &eat.valid_sib, &eat.need_sib, &eat.pcrel,
&insn->rex, calc_bc_dist)) {
case 1:
yasm_expr_destroy(temp);
/* failed, don't bother checking rest of insn */
@ -904,7 +904,8 @@ x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
*/
if (yasm_x86__expr_checkea(&ea->disp, &addrsize,
insn->common.mode_bits, ea->nosplit,
&displen, &eat.modrm, &eat.valid_modrm,
insn->address16_op, &displen,
&eat.modrm, &eat.valid_modrm,
&eat.need_modrm, &eat.sib,
&eat.valid_sib, &eat.need_sib,
&eat.pcrel, &insn->rex,

@ -558,11 +558,11 @@ x86_expr_checkea_getregsize_callback(yasm_expr__item *ei, void *d)
int
yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
unsigned int bits, unsigned int nosplit,
unsigned char *displen, unsigned char *modrm,
unsigned char *v_modrm, unsigned char *n_modrm,
unsigned char *sib, unsigned char *v_sib,
unsigned char *n_sib, unsigned char *pcrel,
unsigned char *rex,
int address16_op, unsigned char *displen,
unsigned char *modrm, unsigned char *v_modrm,
unsigned char *n_modrm, unsigned char *sib,
unsigned char *v_sib, unsigned char *n_sib,
unsigned char *pcrel, unsigned char *rex,
yasm_calc_bc_dist_func calc_bc_dist)
{
yasm_expr *e, *wrt;
@ -898,7 +898,7 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
} havereg = HAVE_NONE;
/* 64-bit mode does not allow 16-bit addresses */
if (bits == 64) {
if (bits == 64 && !address16_op) {
yasm__error(e->line,
N_("16-bit addresses not supported in 64-bit mode"));
return 1;
@ -976,7 +976,7 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
break;
case 16:
/* 64-bit mode does not allow 16-bit addresses */
if (bits == 64) {
if (bits == 64 && !address16_op) {
yasm__error(e->line,
N_("16-bit addresses not supported in 64-bit mode"));
return 1;

@ -860,16 +860,39 @@ static const x86_insn_info incdec_insn[] = {
{OPT_RM|OPS_64|OPA_EA, 0, 0} },
};
/* Arithmetic - "F6" opcodes (div/idiv/mul/neg/not) */
/* Arithmetic - mul/neg/not F6 opcodes */
static const x86_insn_info f6_insn[] = {
{ CPU_Any, MOD_SpAdd, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 1,
{ CPU_Any, MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 1,
{OPT_RM|OPS_8|OPA_EA, 0, 0} },
{ CPU_Any, MOD_SpAdd, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 1,
{ CPU_Any, MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 1,
{OPT_RM|OPS_16|OPA_EA, 0, 0} },
{ CPU_386, MOD_SpAdd, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 1,
{ CPU_386, MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 1,
{OPT_RM|OPS_32|OPA_EA, 0, 0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd, 64, 0, 0, 1, {0xF7, 0, 0}, 0, 1,
{OPT_RM|OPS_64|OPA_EA, 0, 0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, {0xF7, 0, 0}, 0,
1, {OPT_RM|OPS_64|OPA_EA, 0, 0} },
};
/* Arithmetic - div/idiv F6 opcodes
* These allow explicit accumulator in GAS mode.
*/
static const x86_insn_info div_insn[] = {
{ CPU_Any, MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 1,
{OPT_RM|OPS_8|OPA_EA, 0, 0} },
{ CPU_Any, MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 1,
{OPT_RM|OPS_16|OPA_EA, 0, 0} },
{ CPU_386, MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 1,
{OPT_RM|OPS_32|OPA_EA, 0, 0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, {0xF7, 0, 0}, 0,
1, {OPT_RM|OPS_64|OPA_EA, 0, 0} },
/* Versions with explicit accumulator */
{ CPU_Any, MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 2,
{OPT_Areg|OPS_8|OPA_None, OPT_RM|OPS_8|OPA_EA, 0} },
{ CPU_Any, MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 2,
{OPT_Areg|OPS_16|OPA_None, OPT_RM|OPS_16|OPA_EA, 0} },
{ CPU_386, MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 2,
{OPT_Areg|OPS_32|OPA_None, OPT_RM|OPS_32|OPA_EA, 0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, {0xF7, 0, 0}, 0,
2, {OPT_Areg|OPS_64|OPA_None, OPT_RM|OPS_64|OPA_EA, 0} },
};
/* Arithmetic - test instruction */
@ -928,108 +951,127 @@ static const x86_insn_info aadm_insn[] = {
/* Arithmetic - imul */
static const x86_insn_info imul_insn[] = {
{ CPU_Any, 0, 0, 0, 0, 1, {0xF6, 0, 0}, 5, 1,
{ CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0xF6, 0, 0}, 5, 1,
{OPT_RM|OPS_8|OPA_EA, 0, 0} },
{ CPU_Any, 0, 16, 0, 0, 1, {0xF7, 0, 0}, 5, 1,
{ CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0xF7, 0, 0}, 5, 1,
{OPT_RM|OPS_16|OPA_EA, 0, 0} },
{ CPU_386, 0, 32, 0, 0, 1, {0xF7, 0, 0}, 5, 1,
{ CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0xF7, 0, 0}, 5, 1,
{OPT_RM|OPS_32|OPA_EA, 0, 0} },
{ CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0xF7, 0, 0}, 5, 1,
{ CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0xF7, 0, 0}, 5, 1,
{OPT_RM|OPS_64|OPA_EA, 0, 0} },
{ CPU_386, 0, 16, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2,
{ CPU_386, MOD_GasSufW, 16, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2,
{OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} },
{ CPU_386, 0, 32, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2,
{ CPU_386, MOD_GasSufL, 32, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2,
{OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} },
{ CPU_Hammer|CPU_64, 0, 64, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2,
{ CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2,
{OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, 0} },
{ CPU_186, 0, 16, 0, 0, 1, {0x6B, 0, 0}, 0, 3,
{ CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x6B, 0, 0}, 0, 3,
{OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA,
OPT_Imm|OPS_8|OPA_SImm} },
{ CPU_386, 0, 32, 0, 0, 1, {0x6B, 0, 0}, 0, 3,
{ CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x6B, 0, 0}, 0, 3,
{OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA,
OPT_Imm|OPS_8|OPA_SImm} },
{ CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x6B, 0, 0}, 0, 3,
{ CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x6B, 0, 0}, 0, 3,
{OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA,
OPT_Imm|OPS_8|OPA_SImm} },
{ CPU_186, 0, 16, 0, 0, 1, {0x6B, 0, 0}, 0, 2,
{ CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x6B, 0, 0}, 0, 2,
{OPT_Reg|OPS_16|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} },
{ CPU_386, 0, 32, 0, 0, 1, {0x6B, 0, 0}, 0, 2,
{ CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x6B, 0, 0}, 0, 2,
{OPT_Reg|OPS_32|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} },
{ CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x6B, 0, 0}, 0, 2,
{ CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x6B, 0, 0}, 0, 2,
{OPT_Reg|OPS_64|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} },
{ CPU_186, 0, 16, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
{ CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
{OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA,
OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail} },
{ CPU_386, 0, 32, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
{ CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
{OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA,
OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail} },
{ CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
{ CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
{OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA,
OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail} },
{ CPU_186, 0, 16, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
{ CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
{OPT_Reg|OPS_16|OPA_SpareEA,
OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0} },
{ CPU_386, 0, 32, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
{ CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
{OPT_Reg|OPS_32|OPA_SpareEA,
OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0} },
{ CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
{ CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
{OPT_Reg|OPS_64|OPA_SpareEA,
OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0} }
};
/* Shifts - standard */
static const x86_insn_info shift_insn[] = {
{ CPU_Any, MOD_SpAdd, 0, 0, 0, 1, {0xD2, 0, 0}, 0, 2,
{ CPU_Any, MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0xD2, 0, 0}, 0, 2,
{OPT_RM|OPS_8|OPA_EA, OPT_Creg|OPS_8|OPA_None, 0} },
/* FIXME: imm8 is only avail on 186+, but we use imm8 to get to postponed
* ,1 form, so it has to be marked as Any. We need to store the active
* CPU flags somewhere to pass that parse-time info down the line.
*/
{ CPU_Any, MOD_SpAdd, 0, 0, 0, 1, {0xC0, 0xD0, 0}, 0, 2,
{ CPU_Any, MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0xC0, 0xD0, 0}, 0, 2,
{OPT_RM|OPS_8|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm|OPAP_ShiftOp,
0} },
{ CPU_Any, MOD_SpAdd, 16, 0, 0, 1, {0xD3, 0, 0}, 0, 2,
{ CPU_Any, MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0xD3, 0, 0}, 0, 2,
{OPT_RM|OPS_16|OPA_EA, OPT_Creg|OPS_8|OPA_None, 0} },
{ CPU_Any, MOD_SpAdd, 16, 0, 0, 1, {0xC1, 0xD1, 0}, 0, 2,
{ CPU_Any, MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0xC1, 0xD1, 0}, 0, 2,
{OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm|OPAP_ShiftOp,
0} },
{ CPU_Any, MOD_SpAdd, 32, 0, 0, 1, {0xD3, 0, 0}, 0, 2,
{ CPU_Any, MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0xD3, 0, 0}, 0, 2,
{OPT_RM|OPS_32|OPA_EA, OPT_Creg|OPS_8|OPA_None, 0} },
{ CPU_Any, MOD_SpAdd, 32, 0, 0, 1, {0xC1, 0xD1, 0}, 0, 2,
{ CPU_Any, MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0xC1, 0xD1, 0}, 0, 2,
{OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm|OPAP_ShiftOp,
0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd, 64, 0, 0, 1, {0xD3, 0, 0}, 0, 2,
{OPT_RM|OPS_64|OPA_EA, OPT_Creg|OPS_8|OPA_None, 0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd, 64, 0, 0, 1, {0xC1, 0xD1, 0}, 0, 2,
{OPT_RM|OPS_64|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm|OPAP_ShiftOp,
0} }
{ CPU_Hammer|CPU_64, MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, {0xD3, 0, 0}, 0,
2, {OPT_RM|OPS_64|OPA_EA, OPT_Creg|OPS_8|OPA_None, 0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, {0xC1, 0xD1, 0},
0, 2, {OPT_RM|OPS_64|OPA_EA,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm|OPAP_ShiftOp, 0} },
/* In GAS mode, single operands are equivalent to shifting by 1 forms */
{ CPU_Any, MOD_SpAdd|MOD_GasOnly|MOD_GasSufB, 0, 0, 0, 1, {0xD0, 0, 0},
0, 1, {OPT_RM|OPS_8|OPA_EA, 0, 0} },
{ CPU_Any, MOD_SpAdd|MOD_GasOnly|MOD_GasSufW, 16, 0, 0, 1, {0xD1, 0, 0},
0, 1, {OPT_RM|OPS_16|OPA_EA, 0, 0} },
{ CPU_Any, MOD_SpAdd|MOD_GasOnly|MOD_GasSufL, 32, 0, 0, 1, {0xD1, 0, 0},
0, 1, {OPT_RM|OPS_32|OPA_EA, 0, 0} },
{ CPU_Hammer|CPU_64, MOD_SpAdd|MOD_GasOnly|MOD_GasSufQ, 64, 0, 0, 1,
{0xD1, 0, 0}, 0, 1, {OPT_RM|OPS_64|OPA_EA, 0, 0} }
};
/* Shifts - doubleword */
static const x86_insn_info shlrd_insn[] = {
{ CPU_386, MOD_Op1Add, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3,
{ CPU_386, MOD_Op1Add|MOD_GasSufW, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3,
{OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm} },
{ CPU_386, MOD_Op1Add, 16, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3,
{ CPU_386, MOD_Op1Add|MOD_GasSufW, 16, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3,
{OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare,
OPT_Creg|OPS_8|OPA_None} },
{ CPU_386, MOD_Op1Add, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3,
{ CPU_386, MOD_Op1Add|MOD_GasSufL, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3,
{OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm} },
{ CPU_386, MOD_Op1Add, 32, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3,
{ CPU_386, MOD_Op1Add|MOD_GasSufL, 32, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3,
{OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare,
OPT_Creg|OPS_8|OPA_None} },
{ CPU_Hammer|CPU_64, MOD_Op1Add, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3,
{OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm} },
{ CPU_Hammer|CPU_64, MOD_Op1Add, 64, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3,
{OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare,
OPT_Creg|OPS_8|OPA_None} }
{ CPU_Hammer|CPU_64, MOD_Op1Add|MOD_GasSufQ, 64, 0, 0, 2, {0x0F, 0x00, 0},
0, 3, {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm} },
{ CPU_Hammer|CPU_64, MOD_Op1Add|MOD_GasSufQ, 64, 0, 0, 2, {0x0F, 0x01, 0},
0, 3, {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare,
OPT_Creg|OPS_8|OPA_None} },
/* GAS parser supports two-operand form for shift with CL count */
{ CPU_386, MOD_Op1Add|MOD_GasOnly|MOD_GasSufW, 16, 0, 0, 2,
{0x0F, 0x01, 0}, 0, 2,
{OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare, 0} },
{ CPU_386, MOD_Op1Add|MOD_GasOnly|MOD_GasSufL, 32, 0, 0, 2,
{0x0F, 0x01, 0}, 0, 2,
{OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} },
{ CPU_Hammer|CPU_64, MOD_Op1Add|MOD_GasOnly|MOD_GasSufQ, 64, 0, 0, 2,
{0x0F, 0x01, 0}, 0, 2,
{OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare, 0} }
};
/* Control transfer instructions (unconditional) */
@ -1136,17 +1178,31 @@ static const x86_insn_info jmp_insn[] = {
{OPT_Mem|OPS_Any|OPTM_Far|OPA_EA, 0, 0} }
};
static const x86_insn_info retnf_insn[] = {
{ CPU_Any, MOD_Op0Add, 0, 0, 0, 1, {0x01, 0, 0}, 0, 0, {0, 0, 0} },
{ CPU_Any, MOD_Op0Add, 0, 0, 0, 1, {0x00, 0, 0}, 0, 1,
{OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0, 0} }
{ CPU_Any, MOD_Op0Add, 0, 0, 0, 1,
{0x01, 0, 0}, 0, 0, {0, 0, 0} },
{ CPU_Any, MOD_Op0Add, 0, 0, 0, 1,
{0x00, 0, 0}, 0, 1, {OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0, 0} },
/* GAS suffix versions */
{ CPU_Any, MOD_Op0Add|MOD_GasSufW, 16, 0, 0, 1,
{0x01, 0, 0}, 0, 0, {0, 0, 0} },
{ CPU_Any, MOD_Op0Add|MOD_GasSufW, 16, 0, 0, 1,
{0x00, 0, 0}, 0, 1, {OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0, 0} },
{ CPU_Any, MOD_Op0Add|MOD_GasSufL|MOD_GasSufQ, 0, 0, 0, 1,
{0x01, 0, 0}, 0, 0, {0, 0, 0} },
{ CPU_Any, MOD_Op0Add|MOD_GasSufL|MOD_GasSufQ, 0, 0, 0, 1,
{0x00, 0, 0}, 0, 1, {OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0, 0} }
};
static const x86_insn_info enter_insn[] = {
{ CPU_186|CPU_Not64, 0, 0, 0, 0, 1, {0xC8, 0, 0}, 0, 2,
{OPT_Imm|OPS_16|OPS_Relaxed|OPA_EA|OPAP_A16,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} },
{ CPU_Hammer|CPU_64, 0, 64, 64, 0, 1, {0xC8, 0, 0}, 0, 2,
{OPT_Imm|OPS_16|OPS_Relaxed|OPA_EA|OPAP_A16,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }
{ CPU_186|CPU_Not64, MOD_GasNoRev|MOD_GasSufL, 0, 0, 0, 1, {0xC8, 0, 0}, 0,
2, {OPT_Imm|OPS_16|OPS_Relaxed|OPA_EA|OPAP_A16,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} },
{ CPU_Hammer|CPU_64, MOD_GasNoRev|MOD_GasSufQ, 64, 64, 0, 1, {0xC8, 0, 0},
0, 2, {OPT_Imm|OPS_16|OPS_Relaxed|OPA_EA|OPAP_A16,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} },
/* GAS suffix version */
{ CPU_186, MOD_GasOnly|MOD_GasNoRev|MOD_GasSufW, 16, 0, 0, 1,
{0xC8, 0, 0}, 0, 2, {OPT_Imm|OPS_16|OPS_Relaxed|OPA_EA|OPAP_A16,
OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} },
};
/* Conditional jumps */
@ -2034,7 +2090,6 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc,
for (i = num_operands-1, op = yasm_ops_first(operands); op && i >= 0;
op = yasm_operand_next(op), i--)
rev_ops[i] = op;
use_ops = rev_ops;
}
/* If we're running in GAS mode, look at the first insn_info to see
@ -2113,6 +2168,14 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc,
break;
}
/* Use reversed operands in GAS mode if not otherwise specified */
if (arch_x86->parser == X86_PARSER_GAS) {
if (info->modifiers & MOD_GasNoRev)
use_ops = ops;
else
use_ops = rev_ops;
}
/* Match each operand type and size */
for (i = 0, op = use_ops[0]; op && i<info->num_operands && !mismatch;
op = use_ops[++i]) {
@ -3512,29 +3575,48 @@ yasm_x86__parse_check_insn(yasm_arch *arch, unsigned long data[4],
RET_INSN_GAS(4, onebyte, 0x4099, CPU_Hammer|CPU_64);
}
/* Multiplication and division */
M U L { RET_INSN(3, f6, 0x04, CPU_Any); }
I M U L { RET_INSN(4, imul, 0, CPU_Any); }
D I V { RET_INSN(3, f6, 0x06, CPU_Any); }
I D I V { RET_INSN(4, f6, 0x07, CPU_Any); }
M U L [bBwWlLqQ]? { RET_INSN(3, f6, 0x04, CPU_Any); }
I M U L [bBwWlLqQ]? { RET_INSN(4, imul, 0, CPU_Any); }
D I V [bBwWlLqQ]? { RET_INSN(3, div, 0x06, CPU_Any); }
I D I V [bBwWlLqQ]? { RET_INSN(4, div, 0x07, CPU_Any); }
/* Shifts */
R O L { RET_INSN(3, shift, 0x00, CPU_Any); }
R O R { RET_INSN(3, shift, 0x01, CPU_Any); }
R C L { RET_INSN(3, shift, 0x02, CPU_Any); }
R C R { RET_INSN(3, shift, 0x03, CPU_Any); }
S A L { RET_INSN(3, shift, 0x04, CPU_Any); }
S H L { RET_INSN(3, shift, 0x04, CPU_Any); }
S H R { RET_INSN(3, shift, 0x05, CPU_Any); }
S A R { RET_INSN(3, shift, 0x07, CPU_Any); }
S H L D { RET_INSN(4, shlrd, 0xA4, CPU_386); }
S H R D { RET_INSN(4, shlrd, 0xAC, CPU_386); }
R O L [bBwWlLqQ]? { RET_INSN(3, shift, 0x00, CPU_Any); }
R O R [bBwWlLqQ]? { RET_INSN(3, shift, 0x01, CPU_Any); }
R C L [bBwWlLqQ]? { RET_INSN(3, shift, 0x02, CPU_Any); }
R C R [bBwWlLqQ]? { RET_INSN(3, shift, 0x03, CPU_Any); }
S A L [bBwWlLqQ]? { RET_INSN(3, shift, 0x04, CPU_Any); }
S H L [bBwWlLqQ]? { RET_INSN(3, shift, 0x04, CPU_Any); }
S H R [bBwWlLqQ]? { RET_INSN(3, shift, 0x05, CPU_Any); }
S A R [bBwWlLqQ]? { RET_INSN(3, shift, 0x07, CPU_Any); }
S H L D [wWlLqQ]? { RET_INSN(4, shlrd, 0xA4, CPU_386); }
S H R D [wWlLqQ]? { RET_INSN(4, shlrd, 0xAC, CPU_386); }
/* Control transfer instructions (unconditional) */
C A L L { RET_INSN(4, call, 0, CPU_Any); }
J M P { RET_INSN(3, jmp, 0, CPU_Any); }
R E T { RET_INSN(3, retnf, 0xC2, CPU_Any); }
R E T N { RET_INSN(4, retnf, 0xC2, CPU_Any); }
R E T F { RET_INSN(4, retnf, 0xCA, CPU_Any); }
E N T E R { RET_INSN(5, enter, 0, CPU_186); }
R E T W? { RET_INSN(3, retnf, 0xC2, CPU_Any); }
R E T L {
not64 = 1;
RET_INSN_GAS(3, retnf, 0xC2, CPU_Any);
}
R E T Q {
warn64 = 1;
RET_INSN_GAS(3, retnf, 0xC2, CPU_Hammer|CPU_64);
}
R E T N { RET_INSN_NONGAS(4, retnf, 0xC2, CPU_Any); }
R E T F { RET_INSN_NONGAS(4, retnf, 0xCA, CPU_Any); }
L R E T W { RET_INSN_GAS(4, retnf, 0xCA, CPU_Any); }
L R E T L {
not64 = 1;
RET_INSN_GAS(4, retnf, 0xCA, CPU_Any);
}
L R E T Q {
warn64 = 1;
RET_INSN_GAS(4, retnf, 0xCA, CPU_Any);
}
E N T E R [wWlLqQ]? { RET_INSN(5, enter, 0, CPU_186); }
L E A V E { RET_INSN(5, onebyte, 0x4000C9, CPU_186); }
L E A V E [wW] { RET_INSN_GAS(6, onebyte, 0x0010C9, CPU_186); }
L E A V E [lLqQ] { RET_INSN_GAS(6, onebyte, 0x4000C9, CPU_186); }
/* Conditional jumps */
J O { RET_INSN(2, jcc, 0x00, CPU_Any); }
J N O { RET_INSN(3, jcc, 0x01, CPU_Any); }

Loading…
Cancel
Save