From 87d84b7cb8b41a4ebf8dda39edc74acc1382d0e6 Mon Sep 17 00:00:00 2001 From: Joe Soroka Date: Tue, 1 Feb 2011 15:37:58 -0800 Subject: [PATCH] tccasm: allow one-line prefix+op things like "rep stosb" --- i386-asm.c | 5 +++++ i386-asm.h | 4 ++-- tests/asmtest.S | 18 ++++++++++++++++++ tests/tcctest.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/i386-asm.c b/i386-asm.c index 075d2ea..2623ef6 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -574,6 +574,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) static int a32 = 0, o32 = 0, addr32 = 0, data32 = 0; #endif + /* force synthetic ';' after prefix instruction, so we can handle */ + /* one-line things like "rep stosb" instead of only "rep\nstosb" */ + if (opcode >= TOK_ASM_wait && opcode <= TOK_ASM_repnz) + unget_tok(';'); + /* get operands */ pop = ops; nb_ops = 0; diff --git a/i386-asm.h b/i386-asm.h index 94df608..82e269a 100644 --- a/i386-asm.h +++ b/i386-asm.h @@ -33,7 +33,6 @@ DEF_ASM_OP0(iret, 0xcf) DEF_ASM_OP0(rsm, 0x0faa) DEF_ASM_OP0(hlt, 0xf4) - DEF_ASM_OP0(wait, 0x9b) DEF_ASM_OP0(nop, 0x90) DEF_ASM_OP0(xlat, 0xd7) @@ -74,6 +73,8 @@ ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA)) /* prefixes */ + DEF_ASM_OP0(wait, 0x9b) + DEF_ASM_OP0(fwait, 0x9b) #ifdef I386_ASM_16 DEF_ASM_OP0(a32, 0x67) DEF_ASM_OP0(o32, 0x66) @@ -282,7 +283,6 @@ ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA)) DEF_ASM_OP0(fninit, 0xdbe3) DEF_ASM_OP0(fnclex, 0xdbe2) DEF_ASM_OP0(fnop, 0xd9d0) - DEF_ASM_OP0(fwait, 0x9b) /* fp load */ DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST) diff --git a/tests/asmtest.S b/tests/asmtest.S index 0d4c0fc..452815c 100644 --- a/tests/asmtest.S +++ b/tests/asmtest.S @@ -478,6 +478,24 @@ int $0x10 repz repne repnz + nop + + lock ;negl (%eax) + wait ;pushf + rep ;stosb + repe ;lodsb + repz ;cmpsb + repne;movsb + repnz;outsb + + /* handle one-line prefix + ops */ + lock negl (%eax) + wait pushf + rep stosb + repe lodsb + repz cmpsb + repne movsb + repnz outsb invd wbinvd diff --git a/tests/tcctest.c b/tests/tcctest.c index f62983d..3af3d18 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2132,6 +2132,27 @@ __asm__ __volatile__( return dest; } +static char * strncat2(char * dest,const char * src,size_t count) +{ +int d0, d1, d2, d3; +__asm__ __volatile__( + "repne scasb\n\t" /* one-line repne prefix + string op */ + "decl %1\n\t" + "movl %8,%3\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %2,%2\n\t" + "stosb" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) + : "memory"); +return dest; +} + static inline void * memcpy1(void * to, const void * from, size_t n) { int d0, d1, d2; @@ -2150,6 +2171,24 @@ __asm__ __volatile__( return (to); } +static inline void * memcpy2(void * to, const void * from, size_t n) +{ +int d0, d1, d2; +__asm__ __volatile__( + "rep movsl\n\t" /* one-line rep prefix + string op */ + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" + "2:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); +return (to); +} + static __inline__ void sigaddset1(unsigned int *set, int _sig) { __asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc"); @@ -2199,6 +2238,10 @@ void asm_test(void) strncat1(buf, " worldXXXXX", 3); printf("%s\n", buf); + memcpy2(buf, "hello", 6); + strncat2(buf, " worldXXXXX", 3); + printf("%s\n", buf); + /* 'A' constraint test */ printf("mul64=0x%Lx\n", mul64(0x12345678, 0xabcd1234)); printf("inc64=0x%Lx\n", inc64(0x12345678ffffffff));