mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-28 08:10:25 +08:00
update
This commit is contained in:
parent
7808b4046e
commit
75e743d23e
33
Makefile
33
Makefile
@ -13,7 +13,7 @@ CFLAGS+=-m386 -malign-functions=0 -mpreferred-stack-boundary=2
|
|||||||
CFLAGS+=-DCONFIG_TCC_PREFIX=\"$(prefix)\"
|
CFLAGS+=-DCONFIG_TCC_PREFIX=\"$(prefix)\"
|
||||||
DISAS=objdump -d
|
DISAS=objdump -d
|
||||||
INSTALL=install
|
INSTALL=install
|
||||||
VERSION=0.9.15
|
VERSION=0.9.16
|
||||||
|
|
||||||
# run local version of tcc with local libraries and includes
|
# run local version of tcc with local libraries and includes
|
||||||
TCC=./tcc -B. -I.
|
TCC=./tcc -B. -I.
|
||||||
@ -103,7 +103,7 @@ ex3: ex3.c
|
|||||||
|
|
||||||
# Native Tiny C Compiler
|
# Native Tiny C Compiler
|
||||||
|
|
||||||
tcc_g: tcc.c i386-gen.c tccelf.c tcctok.h libtcc.h Makefile
|
tcc_g: tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h Makefile
|
||||||
gcc $(CFLAGS) -o $@ $< $(LIBS)
|
gcc $(CFLAGS) -o $@ $< $(LIBS)
|
||||||
|
|
||||||
tcc: tcc_g
|
tcc: tcc_g
|
||||||
@ -128,17 +128,9 @@ install: tcc libtcc1.o bcheck.o
|
|||||||
clean:
|
clean:
|
||||||
rm -f *~ *.o tcc tcc1 tcct tcc_g tcctest.ref *.bin *.i ex2 \
|
rm -f *~ *.o tcc tcc1 tcct tcc_g tcctest.ref *.bin *.i ex2 \
|
||||||
core gmon.out test.out test.ref a.out tcc_p \
|
core gmon.out test.out test.ref a.out tcc_p \
|
||||||
*.exe iltcc iltcc_g tcc-doc.html \
|
*.exe tcc-doc.html \
|
||||||
tcctest[1234] test[1234].out
|
tcctest[1234] test[1234].out
|
||||||
|
|
||||||
# IL TCC
|
|
||||||
|
|
||||||
iltcc_g: tcc.c il-gen.c bcheck.c Makefile
|
|
||||||
gcc $(CFLAGS) -DTCC_TARGET_IL -o $@ $< $(LIBS)
|
|
||||||
|
|
||||||
iltcc: iltcc_g
|
|
||||||
strip -s -R .comment -R .note -o $@ $<
|
|
||||||
|
|
||||||
# win32 TCC
|
# win32 TCC
|
||||||
tcc_g.exe: tcc.c i386-gen.c bcheck.c Makefile
|
tcc_g.exe: tcc.c i386-gen.c bcheck.c Makefile
|
||||||
i386-mingw32msvc-gcc $(CFLAGS) -DCONFIG_TCC_STATIC -o $@ $<
|
i386-mingw32msvc-gcc $(CFLAGS) -DCONFIG_TCC_STATIC -o $@ $<
|
||||||
@ -176,6 +168,22 @@ libtest: libtcc_test
|
|||||||
instr: instr.o
|
instr: instr.o
|
||||||
objdump -d instr.o
|
objdump -d instr.o
|
||||||
|
|
||||||
|
# tiny assembler testing
|
||||||
|
|
||||||
|
asmtest.ref: asmtest.S
|
||||||
|
gcc -c -o asmtest.ref.o asmtest.S
|
||||||
|
objdump -D asmtest.ref.o > $@
|
||||||
|
|
||||||
|
# XXX: we compute tcc.c to go faster during development !
|
||||||
|
asmtest.out: asmtest.S tcc
|
||||||
|
# ./tcc tcc.c -c asmtest.S
|
||||||
|
#asmtest.out: asmtest.S tcc
|
||||||
|
./tcc -c asmtest.S
|
||||||
|
objdump -D asmtest.o > $@
|
||||||
|
|
||||||
|
asmtest: asmtest.out asmtest.ref
|
||||||
|
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
||||||
|
|
||||||
instr.o: instr.S
|
instr.o: instr.S
|
||||||
gcc -O2 -Wall -g -c -o $@ $<
|
gcc -O2 -Wall -g -c -o $@ $<
|
||||||
|
|
||||||
@ -191,9 +199,8 @@ FILES= Makefile Makefile.uClibc \
|
|||||||
README TODO COPYING \
|
README TODO COPYING \
|
||||||
Changelog tcc-doc.texi tcc-doc.html \
|
Changelog tcc-doc.texi tcc-doc.html \
|
||||||
tcc.1 \
|
tcc.1 \
|
||||||
tcc.c i386-gen.c tccelf.c tcctok.h \
|
tcc.c i386-gen.c tccelf.c tcctok.h tccasm.c i386-asm.c i386-asm.h\
|
||||||
bcheck.c libtcc1.c \
|
bcheck.c libtcc1.c \
|
||||||
il-opcodes.h il-gen.c \
|
|
||||||
elf.h stab.h stab.def \
|
elf.h stab.h stab.def \
|
||||||
stddef.h stdarg.h stdbool.h float.h varargs.h \
|
stddef.h stdarg.h stdbool.h float.h varargs.h \
|
||||||
tcclib.h libtcc.h libtcc_test.c \
|
tcclib.h libtcc.h libtcc_test.c \
|
||||||
|
30
TODO
30
TODO
@ -1,21 +1,33 @@
|
|||||||
TODO list:
|
TODO list:
|
||||||
|
|
||||||
- add statment expressions (linux kernel compilation)
|
- fix asm without input/output (no % preprocessing)
|
||||||
- implement minimal 'asm' extension (linux kernel compilation)
|
- handle inline functions as macros.
|
||||||
- handle static inline, then normal prototype.
|
- see transparent union pb in /urs/include/sys/socket.h
|
||||||
|
- precise behaviour of typeof with arrays ? (__put_user macro)
|
||||||
|
- #include_next support for /usr/include/limits ?
|
||||||
|
but should suffice for most cases)
|
||||||
|
- handle '? x, y : z' in reversed function arguments or unsized
|
||||||
|
variable initialization (',' is considered incorrectly as separator
|
||||||
|
in preparser) : change func argument code generator ?
|
||||||
|
- function pointers/lvalues in ? : (linux kernel net/core/dev.c)
|
||||||
|
- add A x86 asm constraint (linux asm-i386/div64.h)
|
||||||
|
- transform functions to function pointers in function parameters (net/ipv4/ip_output.c)
|
||||||
|
- fix function pointer type display
|
||||||
|
- fix bound exit on RedHat 7.3
|
||||||
|
- fix static link on RedHat 7.3
|
||||||
|
- check lcc test suite -> fix bitfield binary operations
|
||||||
|
- check section alignment in C
|
||||||
|
- fix invalid cast in comparison 'if (v == (int8_t)v)'
|
||||||
|
- packed attribute
|
||||||
|
- look at patches from Scott Lafferty
|
||||||
|
- look at bugs from Jason Petrasko.
|
||||||
- support link once trick (gcc 3.2 / glibc compilation issue)
|
- support link once trick (gcc 3.2 / glibc compilation issue)
|
||||||
- finish varargs.h support (gcc 3.2 testsuite issue)
|
- finish varargs.h support (gcc 3.2 testsuite issue)
|
||||||
- add alloca()
|
- add alloca()
|
||||||
- fix static functions declared inside block
|
- fix static functions declared inside block
|
||||||
- fix bitfield binary operations
|
|
||||||
- C99: add variable size arrays (gcc 3.2 testsuite issue)
|
- C99: add variable size arrays (gcc 3.2 testsuite issue)
|
||||||
- C99: add complex types (gcc 3.2 testsuite issue)
|
- C99: add complex types (gcc 3.2 testsuite issue)
|
||||||
- ignore __extension__ keyword (see 20010328-1.c).
|
|
||||||
- Add __restrict keyword (20010611-1.c).
|
|
||||||
- postfix compound literals (see 20010124-1.c)
|
- postfix compound literals (see 20010124-1.c)
|
||||||
- handle '? x, y : z' in reversed function arguments or unsized
|
|
||||||
variable initialization (',' is considered incorrectly as separator
|
|
||||||
in preparser) : use a "record" parse mode ?
|
|
||||||
- fix multiple unions init
|
- fix multiple unions init
|
||||||
- test includes in libtcc_test.
|
- test includes in libtcc_test.
|
||||||
- look at GCC 3.2 compatibility problems.
|
- look at GCC 3.2 compatibility problems.
|
||||||
|
127
tcc-doc.texi
127
tcc-doc.texi
@ -17,7 +17,7 @@ TCC compiles so @emph{fast} that even for big projects @code{Makefile}s may
|
|||||||
not be necessary.
|
not be necessary.
|
||||||
|
|
||||||
TCC not only supports ANSI C, but also most of the new ISO C99
|
TCC not only supports ANSI C, but also most of the new ISO C99
|
||||||
standard and many GNUC extensions.
|
standard and many GNUC extensions including inline assembly.
|
||||||
|
|
||||||
TCC can also be used to make @emph{C scripts}, i.e. pieces of C source
|
TCC can also be used to make @emph{C scripts}, i.e. pieces of C source
|
||||||
that you run as a Perl or Python script. Compilation is so fast that
|
that you run as a Perl or Python script. Compilation is so fast that
|
||||||
@ -70,6 +70,14 @@ link a.o and b.o together and generate the executable myprog.
|
|||||||
@item tcc -c a.c
|
@item tcc -c a.c
|
||||||
Compile a.c and generate object file a.o
|
Compile a.c and generate object file a.o
|
||||||
|
|
||||||
|
@item tcc -c asmfile.S
|
||||||
|
Preprocess with C preprocess and assemble asmfile.S and generate
|
||||||
|
object file asmfile.o.
|
||||||
|
|
||||||
|
@item tcc -c asmfile.s
|
||||||
|
Assemble (but not preprocess) asmfile.s and generate object file
|
||||||
|
asmfile.o.
|
||||||
|
|
||||||
@item tcc -r -o ab.o a.c b.c
|
@item tcc -r -o ab.o a.c b.c
|
||||||
Compile a.c and b.c, link them together and generate the object file ab.o.
|
Compile a.c and b.c, link them together and generate the object file ab.o.
|
||||||
|
|
||||||
@ -332,6 +340,31 @@ to get the alignment of a type or an expression.
|
|||||||
@code{void *} on the goto label @code{label}. @code{goto *expr} can be
|
@code{void *} on the goto label @code{label}. @code{goto *expr} can be
|
||||||
used to jump on the pointer resulting from @code{expr}.
|
used to jump on the pointer resulting from @code{expr}.
|
||||||
|
|
||||||
|
@item Inline assembly with asm instruction:
|
||||||
|
@example
|
||||||
|
static inline void * my_memcpy(void * to, const void * from, size_t n)
|
||||||
|
{
|
||||||
|
int d0, d1, d2;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"rep ; movsl\n\t"
|
||||||
|
"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);
|
||||||
|
}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
TCC includes its own x86 inline assembler with a @code{gas}-like (GNU
|
||||||
|
assembler) syntax. No intermediate files are generated. GCC 3.x named
|
||||||
|
operands are supported.
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@section TinyCC extensions
|
@section TinyCC extensions
|
||||||
@ -350,6 +383,98 @@ indicate that you use TCC.
|
|||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
|
@chapter TinyCC Assembler
|
||||||
|
|
||||||
|
Since version 0.9.16, TinyCC integrates its own assembler. TinyCC
|
||||||
|
assembler supports a gas-like syntax (GNU assembler). You can
|
||||||
|
desactivate assembler support if you want a smaller TinyCC executable
|
||||||
|
(the C compiler does not rely on the assembler).
|
||||||
|
|
||||||
|
TinyCC Assembler is used to handle files with @file{.S} (C
|
||||||
|
preprocessed assembler) and @file{.s} extensions. It is also used to
|
||||||
|
handle the GNU inline assembler with the @code{asm} keyword.
|
||||||
|
|
||||||
|
@section Syntax
|
||||||
|
|
||||||
|
TinyCC Assembler supports most of the gas syntax. The tokens are the
|
||||||
|
same as C.
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item C and C++ comments are supported.
|
||||||
|
|
||||||
|
@item Identifiers are the same as C, so you cannot use '.' or '$'.
|
||||||
|
|
||||||
|
@item Only 32 bit integer numbers are supported.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section Expressions
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item Integers in decimal, octal and hexa are supported.
|
||||||
|
|
||||||
|
@item Unary operators: +, -, ~.
|
||||||
|
|
||||||
|
@item Binary operators in decreasing priority order:
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
@item *, /, %
|
||||||
|
@item &, |, ^
|
||||||
|
@item +, -
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
@item A value is either an absolute number or a label plus an offset.
|
||||||
|
All operators accept absolute values except '+' and '-'. '+' or '-' can be
|
||||||
|
used to add an offset to a label. '-' supports two labels only if they
|
||||||
|
are the same or if they are both defined and in the same section.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section Labels
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item All labels are considered as local, except undefined ones.
|
||||||
|
|
||||||
|
@item Numeric labels can be used as local @code{gas}-like labels.
|
||||||
|
They can be defined several times in the same source. Use 'b'
|
||||||
|
(backward) or 'f' (forward) as suffix to reference them:
|
||||||
|
|
||||||
|
@example
|
||||||
|
1:
|
||||||
|
jmp 1b /* jump to '1' label before */
|
||||||
|
jmp 1f /* jump to '1' label after */
|
||||||
|
1:
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section Directives
|
||||||
|
|
||||||
|
All directives are preceeded by a '.'. The following directives are
|
||||||
|
supported:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item .align n[,value]
|
||||||
|
@item .skip n[,value]
|
||||||
|
@item .space n[,value]
|
||||||
|
@item .byte value1[,value2...]
|
||||||
|
@item .word value1[,value2...]
|
||||||
|
@item .short value1[,value2...]
|
||||||
|
@item .int value1[,value2...]
|
||||||
|
@item .long value1[,value2...]
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section X86 Assembler
|
||||||
|
|
||||||
|
All X86 opcodes are supported. Only ATT syntax is supported (source
|
||||||
|
then destination operand order). If no size suffix is given, TinyCC
|
||||||
|
tries to guess it from the operand sizes.
|
||||||
|
|
||||||
|
Currently, MMX opcodes are supported but not SSE ones.
|
||||||
|
|
||||||
@chapter TinyCC Linker
|
@chapter TinyCC Linker
|
||||||
|
|
||||||
@section ELF file generation
|
@section ELF file generation
|
||||||
|
181
tcctest.c
181
tcctest.c
@ -67,6 +67,9 @@ void relocation_test(void);
|
|||||||
void old_style_function(void);
|
void old_style_function(void);
|
||||||
void sizeof_test(void);
|
void sizeof_test(void);
|
||||||
void typeof_test(void);
|
void typeof_test(void);
|
||||||
|
void local_label_test(void);
|
||||||
|
void statement_expr_test(void);
|
||||||
|
void asm_test(void);
|
||||||
|
|
||||||
int fib(int n);
|
int fib(int n);
|
||||||
void num(int n);
|
void num(int n);
|
||||||
@ -200,7 +203,7 @@ void macro_test(void)
|
|||||||
#line 203 "test"
|
#line 203 "test"
|
||||||
printf("__LINE__=%d __FILE__=%s\n",
|
printf("__LINE__=%d __FILE__=%s\n",
|
||||||
__LINE__, __FILE__);
|
__LINE__, __FILE__);
|
||||||
#line 200 "tcctest.c"
|
#line 206 "tcctest.c"
|
||||||
|
|
||||||
/* not strictly preprocessor, but we test it there */
|
/* not strictly preprocessor, but we test it there */
|
||||||
#ifdef C99_MACROS
|
#ifdef C99_MACROS
|
||||||
@ -467,6 +470,9 @@ int main(int argc, char **argv)
|
|||||||
old_style_function();
|
old_style_function();
|
||||||
sizeof_test();
|
sizeof_test();
|
||||||
typeof_test();
|
typeof_test();
|
||||||
|
statement_expr_test();
|
||||||
|
local_label_test();
|
||||||
|
asm_test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -839,6 +845,16 @@ void bool_test()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* test ? : GCC extension */
|
||||||
|
{
|
||||||
|
static int v1 = 34 ? : -1; /* constant case */
|
||||||
|
static int v2 = 0 ? : -1; /* constant case */
|
||||||
|
int a = 30;
|
||||||
|
|
||||||
|
printf("%d %d\n", v1, v2);
|
||||||
|
printf("%d %d\n", a - 30 ? : a * 2, a + 1 ? : a * 2);
|
||||||
|
}
|
||||||
|
|
||||||
/* again complex expression */
|
/* again complex expression */
|
||||||
for(i=0;i<256;i++) {
|
for(i=0;i<256;i++) {
|
||||||
if (toupper1 (i) != TOUPPER (i))
|
if (toupper1 (i) != TOUPPER (i))
|
||||||
@ -846,7 +862,13 @@ void bool_test()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GCC accepts that */
|
||||||
|
static int tab_reinit[];
|
||||||
|
static int tab_reinit[10];
|
||||||
|
|
||||||
|
//int cinit1; /* a global variable can be defined several times without error ! */
|
||||||
|
int cinit1;
|
||||||
|
int cinit1;
|
||||||
int cinit1 = 0;
|
int cinit1 = 0;
|
||||||
int *cinit2 = (int []){3, 2, 1};
|
int *cinit2 = (int []){3, 2, 1};
|
||||||
|
|
||||||
@ -1072,6 +1094,12 @@ struct bar {
|
|||||||
"a2", 1
|
"a2", 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int sinit18[10] = {
|
||||||
|
[2 ... 5] = 20,
|
||||||
|
2,
|
||||||
|
[8] = 10,
|
||||||
|
};
|
||||||
|
|
||||||
void init_test(void)
|
void init_test(void)
|
||||||
{
|
{
|
||||||
int linit1 = 2;
|
int linit1 = 2;
|
||||||
@ -1161,8 +1189,12 @@ void init_test(void)
|
|||||||
printf("sinit17=%s %d %s %d\n",
|
printf("sinit17=%s %d %s %d\n",
|
||||||
sinit17[0].s, sinit17[0].len,
|
sinit17[0].s, sinit17[0].len,
|
||||||
sinit17[1].s, sinit17[1].len);
|
sinit17[1].s, sinit17[1].len);
|
||||||
|
for(i=0;i<10;i++)
|
||||||
|
printf("%x ", sinit18[i]);
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void switch_test()
|
void switch_test()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -1659,3 +1691,150 @@ void typeof_test(void)
|
|||||||
c = 3.5;
|
c = 3.5;
|
||||||
printf("a=%f b=%f c=%f\n", a, b, c);
|
printf("a=%f b=%f c=%f\n", a, b, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void statement_expr_test(void)
|
||||||
|
{
|
||||||
|
int a, i;
|
||||||
|
|
||||||
|
a = 0;
|
||||||
|
for(i=0;i<10;i++) {
|
||||||
|
a += 1 +
|
||||||
|
( { int b, j;
|
||||||
|
b = 0;
|
||||||
|
for(j=0;j<5;j++)
|
||||||
|
b += j; b;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
printf("a=%d\n", a);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void local_label_test(void)
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
goto l1;
|
||||||
|
l2:
|
||||||
|
a = 1 + ({
|
||||||
|
__label__ l1, l2, l3;
|
||||||
|
goto l4;
|
||||||
|
l5:
|
||||||
|
printf("aa1\n");
|
||||||
|
goto l1;
|
||||||
|
l2:
|
||||||
|
printf("aa3\n");
|
||||||
|
goto l3;
|
||||||
|
l1:
|
||||||
|
printf("aa2\n");
|
||||||
|
goto l2;
|
||||||
|
l3:;
|
||||||
|
1;
|
||||||
|
});
|
||||||
|
printf("a=%d\n", a);
|
||||||
|
return;
|
||||||
|
l1:
|
||||||
|
printf("bb1\n");
|
||||||
|
goto l2;
|
||||||
|
l4:
|
||||||
|
printf("bb2\n");
|
||||||
|
goto l5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inline assembler test */
|
||||||
|
#ifdef __i386__
|
||||||
|
|
||||||
|
/* from linux kernel */
|
||||||
|
static char * strncat1(char * dest,const char * src,size_t count)
|
||||||
|
{
|
||||||
|
int d0, d1, d2, d3;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"repne\n\t"
|
||||||
|
"scasb\n\t"
|
||||||
|
"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;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"rep ; movsl\n\t"
|
||||||
|
"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");
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void sigdelset1(unsigned int *set, int _sig)
|
||||||
|
{
|
||||||
|
asm("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ __const__ unsigned int swab32(unsigned int x)
|
||||||
|
{
|
||||||
|
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
|
||||||
|
"rorl $16,%0\n\t" /* swap words */
|
||||||
|
"xchgb %b0,%h0" /* swap higher bytes */
|
||||||
|
:"=q" (x)
|
||||||
|
: "0" (x));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int set;
|
||||||
|
|
||||||
|
void asm_test(void)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
printf("inline asm:\n");
|
||||||
|
memcpy1(buf, "hello", 6);
|
||||||
|
strncat1(buf, " worldXXXXX", 3);
|
||||||
|
printf("%s\n", buf);
|
||||||
|
|
||||||
|
set = 0xff;
|
||||||
|
sigdelset1(&set, 2);
|
||||||
|
sigaddset1(&set, 16);
|
||||||
|
/* NOTE: we test here if C labels are correctly restored after the
|
||||||
|
asm statement */
|
||||||
|
goto label1;
|
||||||
|
label2:
|
||||||
|
__asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
|
||||||
|
printf("set=0x%x\n", set);
|
||||||
|
val = 0x01020304;
|
||||||
|
printf("swab32(0x%08x) = 0x%0x\n", val, swab32(val));
|
||||||
|
return;
|
||||||
|
label1:
|
||||||
|
goto label2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void asm_test(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user