📄 libgcc2.c
字号:
/* Like bcmp except the sign is meaningful. Result is negative if S1 is less than S2, positive if S1 is greater, 0 if S1 and S2 are equal. */int__gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size){ while (size > 0) { unsigned char c1 = *s1++, c2 = *s2++; if (c1 != c2) return c1 - c2; size--; } return 0;}#endif#ifdef L__dummyvoid__dummy () {}#endif#ifdef L_varargs#ifdef __i860__#if defined(__svr4__) || defined(__alliant__) asm (" .text"); asm (" .align 4");/* The Alliant needs the added underscore. */ asm (".globl __builtin_saveregs");asm ("__builtin_saveregs:"); asm (".globl ___builtin_saveregs");asm ("___builtin_saveregs:"); asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */ asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save area and also for a new va_list structure */ /* Save all argument registers in the arg reg save area. The arg reg save area must have the following layout (according to the svr4 ABI): struct { union { float freg[8]; double dreg[4]; } float_regs; long ireg[12]; }; */ asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */ asm (" fst.q %f12,16(%sp)"); asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */ asm (" st.l %r17,36(%sp)"); asm (" st.l %r18,40(%sp)"); asm (" st.l %r19,44(%sp)"); asm (" st.l %r20,48(%sp)"); asm (" st.l %r21,52(%sp)"); asm (" st.l %r22,56(%sp)"); asm (" st.l %r23,60(%sp)"); asm (" st.l %r24,64(%sp)"); asm (" st.l %r25,68(%sp)"); asm (" st.l %r26,72(%sp)"); asm (" st.l %r27,76(%sp)"); asm (" adds 80,%sp,%r16"); /* compute the address of the new va_list structure. Put in into r16 so that it will be returned to the caller. */ /* Initialize all fields of the new va_list structure. This structure looks like: typedef struct { unsigned long ireg_used; unsigned long freg_used; long *reg_base; long *mem_ptr; } va_list; */ asm (" st.l %r0, 0(%r16)"); /* nfixed */ asm (" st.l %r0, 4(%r16)"); /* nfloating */ asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */ asm (" bri %r1"); /* delayed return */ asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */#else /* not __svr4__ */#if defined(__PARAGON__) /* * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax, * and we stand a better chance of hooking into libraries * compiled by PGI. [andyp@ssd.intel.com] */ asm (" .text"); asm (" .align 4"); asm (".globl __builtin_saveregs");asm ("__builtin_saveregs:"); asm (".globl ___builtin_saveregs");asm ("___builtin_saveregs:"); asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */ asm (" adds -96,sp,sp"); /* allocate stack space for reg save area and also for a new va_list structure */ /* Save all argument registers in the arg reg save area. The arg reg save area must have the following layout (according to the svr4 ABI): struct { union { float freg[8]; double dreg[4]; } float_regs; long ireg[12]; }; */ asm (" fst.q f8, 0(sp)"); asm (" fst.q f12,16(sp)"); asm (" st.l r16,32(sp)"); asm (" st.l r17,36(sp)"); asm (" st.l r18,40(sp)"); asm (" st.l r19,44(sp)"); asm (" st.l r20,48(sp)"); asm (" st.l r21,52(sp)"); asm (" st.l r22,56(sp)"); asm (" st.l r23,60(sp)"); asm (" st.l r24,64(sp)"); asm (" st.l r25,68(sp)"); asm (" st.l r26,72(sp)"); asm (" st.l r27,76(sp)"); asm (" adds 80,sp,r16"); /* compute the address of the new va_list structure. Put in into r16 so that it will be returned to the caller. */ /* Initialize all fields of the new va_list structure. This structure looks like: typedef struct { unsigned long ireg_used; unsigned long freg_used; long *reg_base; long *mem_ptr; } va_list; */ asm (" st.l r0, 0(r16)"); /* nfixed */ asm (" st.l r0, 4(r16)"); /* nfloating */ asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */ asm (" bri r1"); /* delayed return */ asm (" st.l r28,12(r16)"); /* pointer to overflow args */#else /* not __PARAGON__ */ asm (" .text"); asm (" .align 4"); asm (".globl ___builtin_saveregs"); asm ("___builtin_saveregs:"); asm (" mov sp,r30"); asm (" andnot 0x0f,sp,sp"); asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack *//* Fill in the __va_struct. */ asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */ asm (" st.l r17, 4(sp)"); /* int fixed[12] */ asm (" st.l r18, 8(sp)"); asm (" st.l r19,12(sp)"); asm (" st.l r20,16(sp)"); asm (" st.l r21,20(sp)"); asm (" st.l r22,24(sp)"); asm (" st.l r23,28(sp)"); asm (" st.l r24,32(sp)"); asm (" st.l r25,36(sp)"); asm (" st.l r26,40(sp)"); asm (" st.l r27,44(sp)"); asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */ asm (" fst.q f12,64(sp)"); /* int floating[8] *//* Fill in the __va_ctl. */ asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */ asm (" st.l r28,84(sp)"); /* pointer to more args */ asm (" st.l r0, 88(sp)"); /* nfixed */ asm (" st.l r0, 92(sp)"); /* nfloating */ asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */ asm (" bri r1"); asm (" mov r30,sp"); /* recover stack and pass address to start of data. */#endif /* not __PARAGON__ */#endif /* not __svr4__ */#else /* not __i860__ */#ifdef __sparc__ asm (".global __builtin_saveregs"); asm ("__builtin_saveregs:"); asm (".global ___builtin_saveregs"); asm ("___builtin_saveregs:");#ifdef NEED_PROC_COMMAND asm (".proc 020");#endif asm ("st %i0,[%fp+68]"); asm ("st %i1,[%fp+72]"); asm ("st %i2,[%fp+76]"); asm ("st %i3,[%fp+80]"); asm ("st %i4,[%fp+84]"); asm ("retl"); asm ("st %i5,[%fp+88]");#ifdef NEED_TYPE_COMMAND asm (".type __builtin_saveregs,#function"); asm (".size __builtin_saveregs,.-__builtin_saveregs");#endif#else /* not __sparc__ */#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__) asm (" .text"); asm (" .ent __builtin_saveregs"); asm (" .globl __builtin_saveregs"); asm ("__builtin_saveregs:"); asm (" sw $4,0($30)"); asm (" sw $5,4($30)"); asm (" sw $6,8($30)"); asm (" sw $7,12($30)"); asm (" j $31"); asm (" .end __builtin_saveregs");#else /* not __mips__, etc. */void *__builtin_saveregs (){ abort ();}#endif /* not __mips__ */#endif /* not __sparc__ */#endif /* not __i860__ */#endif#ifdef L_eprintf#ifndef inhibit_libc#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */#include <stdio.h>/* This is used by the `assert' macro. */void__eprintf (const char *string, const char *expression, int line, const char *filename){ fprintf (stderr, string, expression, line, filename); fflush (stderr); abort ();}#endif#endif#ifdef L_bb/* Structure emitted by -a */struct bb{ long zero_word; const char *filename; long *counts; long ncounts; struct bb *next; const unsigned long *addresses; /* Older GCC's did not emit these fields. */ long nwords; const char **functions; const long *line_nums; const char **filenames; char *flags;};#ifdef BLOCK_PROFILER_CODEBLOCK_PROFILER_CODE#else#ifndef inhibit_libc/* Simple minded basic block profiling output dumper for systems that don't provide tcov support. At present, it requires atexit and stdio. */#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */#include <stdio.h>char *ctime ();#include "gbl-ctors.h"#include "gcov-io.h"static struct bb *bb_head;/* Return the number of digits needed to print a value *//* __inline__ */ static int num_digits (long value, int base){ int minus = (value < 0 && base != 16); unsigned long v = (minus) ? -value : value; int ret = minus; do { v /= base; ret++; } while (v); return ret;}void__bb_exit_func (void){ FILE *da_file, *file; long time_value; int i; if (bb_head == 0) return; i = strlen (bb_head->filename) - 3; if (!strcmp (bb_head->filename+i, ".da")) { /* Must be -fprofile-arcs not -a. Dump data in a form that gcov expects. */ struct bb *ptr; for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) { /* If the file exists, and the number of counts in it is the same, then merge them in. */ if ((da_file = fopen (ptr->filename, "r")) != 0) { long n_counts = 0; unsigned char tmp; int i; int ret = 0; if (__read_long (&n_counts, da_file, 8) != 0) { fprintf (stderr, "arc profiling: Can't read output file %s.\n", ptr->filename); continue; } if (n_counts == ptr->ncounts) { int i; for (i = 0; i < n_counts; i++) { long v = 0; unsigned char tmp; int j; int ret = 0; if (__read_long (&v, da_file, 8) != 0) { fprintf (stderr, "arc profiling: Can't read output file %s.\n", ptr->filename); break; } ptr->counts[i] += v; } } if (fclose (da_file) == EOF) fprintf (stderr, "arc profiling: Error closing output file %s.\n", ptr->filename); } if ((da_file = fopen (ptr->filename, "w")) == 0) { fprintf (stderr, "arc profiling: Can't open output file %s.\n", ptr->filename); continue; } /* ??? Should first write a header to the file. Preferably, a 4 byte magic number, 4 bytes containing the time the program was compiled, 4 bytes containing the last modification time of the source file, and 4 bytes indicating the compiler options used. That way we can easily verify that the proper source/executable/ data file combination is being used from gcov. */ if (__write_long (ptr->ncounts, da_file, 8) != 0) { fprintf (stderr, "arc profiling: Error writing output file %s.\n", ptr->filename); } else { int j; long *count_ptr = ptr->counts; int ret = 0; for (j = ptr->ncounts; j > 0; j--) { if (__write_long (*count_ptr, da_file, 8) != 0) { ret=1; break; } count_ptr++; } if (ret) fprintf (stderr, "arc profiling: Error writing output file %s.\n", ptr->filename); } if (fclose (da_file) == EOF) fprintf (stderr, "arc profiling: Error closing output file %s.\n", ptr->filename); } return; } /* Must be basic block profiling. Emit a human readable output file. */ file = fopen ("bb.out", "a"); if (!file) perror ("bb.out"); else { struct bb *ptr; /* This is somewhat type incorrect, but it avoids worrying about exactly where time.h is included from. It should be ok unless a void * differs from other pointer formats, or if sizeof (long) is < sizeof (time_t). It would be nice if we could assume the use of rationale standards here. */ time ((void *) &time_value); fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value)); /* We check the length field explicitly in order to allow compatibility with older GCC's which did not provide it. */ for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) { int i; int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000 && ptr->functions); int line_p = (func_p && ptr->line_nums); int file_p = (func_p && ptr->filenames); int addr_p = (ptr->addresses != 0); long ncounts = ptr->ncounts; long cnt_max = 0; long line_max = 0; long addr_max = 0; int file_len = 0; int func_len = 0; int blk_len = num_digits (ncounts, 10); int cnt_len; int line_len; int addr_len; fprintf (file, "File %s, %ld basic blocks \n\n", ptr->filename, ncounts); /* Get max values for each field. */ for (i = 0; i < ncounts; i++) { const char *p; int len; if (cnt_max < ptr->counts[i]) cnt_max = ptr->counts[i]; if (addr_p && addr_max < ptr->addresses[i]) addr_max = ptr->addresses[i]; if (line_p && line_max < ptr->line_nums[i]) line_max = ptr->line_nums[i]; if (func_p) { p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>"; len = strlen (p); if (func_len < len) func_len = len; } if (file_p) { p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>"; len = strlen (p); if (file_len < len) file_len = len; } } addr_len = num_digits (addr_max, 16); cnt_len = num_digits (cnt_max, 10); line_len = num_digits (line_max, 10); /* Now print out the basic block information. */ for (i = 0; i < ncounts; i++) { fprintf (file, " Block #%*d: executed %*ld time(s)", blk_len, i+1, cnt_len, ptr->counts[i]); if (addr_p) fprintf (file, " address= 0x%.*lx", addr_len, ptr->addresses[i]); if (func_p) fprintf (file, " function= %-*s", func_len, (ptr->functions[i]) ? ptr->functions[i] : "<none>"); if (line_p) fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]); if (file_p) fprintf (file, " file= %s", (ptr->filenames[i]) ? ptr->filenames[i] : "<none>"); fprintf (file, "\n"); } fprintf (file, "\n"); fflush (file); } fprintf (file, "\n\n"); fclose (file); }}void__bb_init_func (struct bb *blocks){ /* User is supposed to check whether the first word is non-0, but just in case.... */ if (blocks->zero_word) return;#ifdef ON_EXIT /* Initialize destructor. */ if (!bb_head) ON_EXIT (__bb_exit_func, 0);#endif /* Set up linked list. */ blocks->zero_word = 1; blocks->next = bb_head; bb_head = blocks;}#ifndef MACHINE_STATE_SAVE#define MACHINE_STATE_SAVE(ID)#endif#ifndef MACHINE_STATE_RESTORE#define MACHINE_STATE_RESTORE(ID)#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -