aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2017-12-03 04:53:50 +0100
committerMichael Matz <matz@suse.de>2017-12-03 04:53:50 +0100
commit529b44c0d53955309e79de3da677973922f48425 (patch)
tree58bcc97ded93a0a207e1d9514d5c86c9c6832915
parent9e0d23cc47359149a39eafffdbb133963980b6ed (diff)
downloadtinycc-529b44c0d53955309e79de3da677973922f48425.tar.gz
tinycc-529b44c0d53955309e79de3da677973922f48425.tar.bz2
tccasm: Accept suffixed cmovCC
The length suffix for cmovCC isn't necessary as the required register operands always allow length deduction. But let's be nice to users and accept them anyway. Do that without blowing up tables, which means we don't detect invalid suffixes for the given operands, but so be it.
-rw-r--r--i386-asm.c18
-rw-r--r--tests/asmtest.S3
2 files changed, 17 insertions, 4 deletions
diff --git a/i386-asm.c b/i386-asm.c
index 1b992ca..55c95af 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -727,6 +727,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
s = 0; /* avoid warning */
+again:
/* optimize matching by using a lookup table (no hashing is needed
!) */
for(pa = asm_instrs; pa->sym != 0; pa++) {
@@ -757,8 +758,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
continue;
/* cmovxx is a test opcode but accepts multiple sizes.
- TCC doesn't accept the suffixed mnemonic, instead we
- simply force size autodetection always. */
+ The suffixes aren't encoded in the table, instead we
+ simply force size autodetection always and deal with suffixed
+ variants below when we don't find e.g. "cmovzl". */
if (pa->instr_type & OPC_WLX)
s = NBWLX - 1;
} else if (pa->instr_type & OPC_B) {
@@ -844,8 +846,16 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
tcc_error("bad operand with opcode '%s'",
get_tok_str(opcode, NULL));
} else {
- tcc_error("unknown opcode '%s'",
- get_tok_str(opcode, NULL));
+ /* Special case for cmovcc, we accept size suffixes but ignore
+ them, but we don't want them to blow up our tables. */
+ TokenSym *ts = table_ident[opcode - TOK_IDENT];
+ if (ts->len >= 6
+ && strchr("wlq", ts->str[ts->len-1])
+ && !memcmp(ts->str, "cmov", 4)) {
+ opcode = tok_alloc(ts->str, ts->len-1)->tok;
+ goto again;
+ }
+ tcc_error("unknown opcode '%s'", ts->str);
}
}
/* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
diff --git a/tests/asmtest.S b/tests/asmtest.S
index 5578705..e9c0e32 100644
--- a/tests/asmtest.S
+++ b/tests/asmtest.S
@@ -577,10 +577,13 @@ fucomip %st(5), %st
cmovs 0x1000, %eax
cmovns %edx, %edi
cmovne %ax, %si
+ cmovbw %ax, %di
+ cmovnbel %edx, %ecx
#ifdef __x86_64__
bswapq %rsi
bswapq %r10
cmovz %rdi,%rbx
+ cmovpeq %rsi, %rdx
#endif
int $3