aboutsummaryrefslogtreecommitdiff
path: root/i386-asm.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-05-15 06:54:42 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:05 +0100
commited35ac841b9e9c3c8cec8459ec84833f483af959 (patch)
tree61c2c582ed6ff69023f51ec7bd46f5115f729831 /i386-asm.c
parent2b7ee000cd3dd49283f73a95bb0a09cb2de7039f (diff)
downloadtinycc-ed35ac841b9e9c3c8cec8459ec84833f483af959.tar.gz
tinycc-ed35ac841b9e9c3c8cec8459ec84833f483af959.tar.bz2
x86-asm: Add more SSE2 instructions
In particular those that are extensions of existing mmx (or sse1) instructions by a simple 0x66 prefix. There's one caveat for x86-64: as we don't yet correctly handle the 0xf3 prefix the movq mem64->xmm is wrong (tested in asmtest.S). Needs some refactoring of the instr_type member.
Diffstat (limited to 'i386-asm.c')
-rw-r--r--i386-asm.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/i386-asm.c b/i386-asm.c
index a7563ab..16916f9 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -27,7 +27,7 @@
#define TOK_ASM_first TOK_ASM_clc
#define TOK_ASM_last TOK_ASM_emms
-#define TOK_ASM_alllast TOK_ASM_pxor
+#define TOK_ASM_alllast TOK_ASM_subps
#define OPC_JMP 0x01 /* jmp operand */
#define OPC_B 0x02 /* only used with OPC_WL */
@@ -89,6 +89,7 @@ enum {
OPT_REG, /* REG8 | REG16 | REG32 | REG64 */
OPT_REGW, /* REG16 | REG32 | REG64 */
OPT_IMW, /* IM16 | IM32 */
+ OPT_MMXSSE, /* MMX | SSE */
/* can be ored with any OPT_xxx */
OPT_EA = 0x80
};
@@ -512,6 +513,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
int op_type[3]; /* decoded op type */
int alltypes; /* OR of all operand types */
int autosize;
+ int p66;
/* force synthetic ';' after prefix instruction, so we can handle */
/* one-line things like "rep stosb" instead of only "rep\nstosb" */
@@ -630,6 +632,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
case OPT_IMW:
v = OP_IM16 | OP_IM32;
break;
+ case OPT_MMXSSE:
+ v = OP_MMX | OP_SSE;
+ break;
default:
v = 1 << op2;
break;
@@ -693,7 +698,19 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
}
#endif
/* generate data16 prefix if needed */
+ p66 = 0;
if (s == 1 || (pa->instr_type & OPC_D16))
+ p66 = 1;
+ else {
+ /* accepting mmx+sse in all operands --> needs 0x66 to
+ switch to sse mode. Accepting only sse in an operand --> is
+ already SSE insn and needs 0x66/f2/f3 handling. */
+ for (i = 0; i < nb_ops; i++)
+ if ((op_type[i] & (OP_MMX | OP_SSE)) == (OP_MMX | OP_SSE)
+ && ops[i].type & OP_SSE)
+ p66 = 1;
+ }
+ if (p66)
g(0x66);
#ifdef TCC_TARGET_X86_64
if (s == 3 || (alltypes & OP_REG64)) {