/programs/develop/ktcc/trunk/libc/include/conio.h |
---|
0,0 → 1,197 |
/* |
This is adapded thunk for console.obj sys library |
.h is equal to svn:\programs\develop\libraries\console\console_en.txt |
Adapted for tcc by Siemargl, 2016 |
*/ |
#ifndef __conio_h |
#define __conio_h |
#define cdecl __attribute__ ((cdecl)) |
#define stdcall __attribute__ ((stdcall)) |
/* |
console.obj exports the following functions |
*/ |
typedef unsigned long dword; /* 32-bit unsigned integer */ |
typedef unsigned short word; /* 16-bit unsigned integer */ |
extern void stdcall (*con_init)(dword wnd_width, dword wnd_height, |
dword scr_width, dword scr_height, const char* title); |
/* Console initialization. Must be called only once. |
wnd_width, wnd_height - width and height (in units of characters) of the visible |
region; |
scr_width, scr_height - width and height (in units of characters) of console; |
Any of these four parameters can be set to -1 (=0xFFFFFFFF) |
to use the library's default values; |
title - console window's caption. */ |
extern void stdcall (*con_exit)(int bCloseWindow); |
/* You should call this funstion at the end of the program. |
If bCloseWindow is zero, the string "[Finished]" will be added to the caption of |
the window and the console window will remain on the screen until the user |
closes it. */ |
extern void stdcall (*con_set_title)(const char* title); |
/* Set new window caption. */ |
extern void stdcall (*con_write_asciiz)(const char* str); |
/* Display ASCIIZ-string to the console at the current position, shifting |
the current position. */ |
extern void stdcall (*con_write_string)(const char* str, dword length); |
/* Similar to con_write_asciiz, but length of the string must be given as a |
separate parameter */ |
extern int cdecl (*con_printf)(const char* format, ...); |
/* Standard "printf" function from ANSI C. */ |
extern dword stdcall (*con_get_flags)(void); |
/* Get output flags. */ |
extern dword stdcall (*con_set_flags)(dword new_flags); |
/* Set output flags. This function returns previous values. */ |
/* Flags (bitmask): */ |
/* text color */ |
#define CON_COLOR_BLUE 0x01 |
#define CON_COLOR_GREEN 0x02 |
#define CON_COLOR_RED 0x04 |
#define CON_COLOR_BRIGHT 0x08 |
/* background color */ |
#define CON_BGR_BLUE 0x10 |
#define CON_BGR_GREEN 0x20 |
#define CON_BGR_RED 0x40 |
#define CON_BGR_BRIGHT 0x80 |
/* output controls */ |
#define CON_IGNORE_SPECIALS 0x100 |
/* if this flag is cleared, function interprets special characters: |
10 ('\n') - next line |
13 ('\r') - carriage return |
8 ('\b') - backspace |
9 ('\t') - tab |
27 ('\033' = '\x1B') - the beginning of Esc-sequences; |
otherwise, these characters will be displayed like ordinary characters. */ |
/* Supported Esc-sequences: |
Esc[<number1>;<number2>;<number3>m - choice of character attributes: |
You can specify one, two or three codes in any order; |
0 = normal mode (white on black) |
1 = bright selection |
5 = bright background |
7 = inverse mode (black on white) |
30 = black characters |
31 = red characters |
32 = green characters |
33 = brown characters |
34 = blue characters |
35 = purple characters |
36 = turqoise characters |
37 = white characters |
40 = black background |
41 = red background |
42 = green background |
43 = brown background |
44 = blue background |
45 = purple background |
46 = turqoise background |
47 = white background |
The following sequences appeared in version 5 of library: |
Esc[2J - clear screen, move cursor to upper left corner |
Esc[<number1>;<number2>H = Esc[<number1>;<number2>f - |
move cursor to <number1>,<number2> |
Esc[<number>A - move cursor to <number> lines up |
Esc[<number>B - move cursor to <number> lines down |
Esc[<number>C - move cursor to <number> positions right |
Esc[<number>D - move cursor to <number> positions left |
*/ |
/* signal "console closed"; appeared in version 6; |
ignored by con_set_flags */ |
#define CON_WINDOW_CLOSED 0x200 |
/* The default value for flags = 7. (grey text on black background) */ |
extern int stdcall (*con_get_font_height)(void); |
/* Get the height of the font. */ |
extern int stdcall (*con_get_cursor_height)(void); |
/* Get the height of the cursor. */ |
extern int stdcall (*con_set_cursor_height)(int new_height); |
/* Set the height of the cursor. This function returns previous value. |
An attempt to set the value out of the correct interval (from 0 to |
font_height-1) is ignored. |
Cursor with zero height isn't displayed. |
Default value: - 15% from font height. */ |
extern int stdcall (*con_getch)(void); |
/* Get one character from the keyboard. |
For normal characters function returns ASCII-code. For extended |
characters (eg, Fx, and arrows), first function call returns 0 |
and second call returns the extended code (similar to the DOS-function |
input). Starting from version 7, after closing the console window, |
this function returns 0. */ |
extern word stdcall (*con_getch2)(void); |
/* Reads a character from the keyboard. Low byte contains the ASCII-code |
(0 for extended characters), high byte - advanced code (like in BIOS |
input functions). Starting from version 7, after closing the console |
window, this function returns 0. */ |
extern int stdcall (*con_kbhit)(void); |
/* Returns 1 if a key was pressed, 0 otherwise. To read pressed keys use |
con_getch and con_getch2. Starting from version 6, after closing |
the console window, this function returns 1. */ |
extern char* stdcall (*con_gets)(char* str, int n); |
/* Reads a string from the keyboard. Reading is interrupted when got |
"new line" character, or after reading the (n-1) characters (depending on |
what comes first). In the first case the newline is also recorded in the |
str. The acquired line is complemented by a null character. |
Starting from version 6, the function returns a pointer to the entered |
line if reading was successful, and NULL if the console window was closed. */ |
typedef int (stdcall * con_gets2_callback)(int keycode, char** pstr, int* pn, |
int* ppos); |
extern char* stdcall (*con_gets2)(con_gets2_callback callback, char* str, int n); |
/* Con_gets completely analogous, except that when the user |
press unrecognized key, it calls the specified callback-procedure |
(which may, for example, handle up / down for history and tab to enter |
autocompletion). You should pass to the procedure: key code and three pointers |
- to the string, to the maximum length and to the current position. |
function may change the contents of string and may change the string |
itself (for example, to reallocate memory for increase the limit), |
maximum length, and position of the line - pointers are passed for it. |
Return value: 0 = line wasn't changed 1 = line changed, you should |
remove old string and display new, 2 = line changed, it is necessary |
to display it; 3 = immediately exit the function. |
Starting from version 6, the function returns a pointer to the entered |
line with the successful reading, and NULL if the console window was closed. */ |
extern void stdcall (*con_cls)(); |
/* Clear screen and set cursor at upper left corner. */ |
extern void stdcall (*con_get_cursor_pos)(int* px, int* py); |
/* Wrote current (x) coordinate of cursor to *px, and (y) to *py. */ |
extern void stdcall (*con_set_cursor_pos)(int x, int y); |
/* Set the cursor position to the specified coordinates. If any of the |
parameters beyond the relevant range (from 0 to 1 scr_width- |
for x, from 0 to 1 for scr_height-y, scr_width scr_height and were asked if |
call con_init), then the corresponding coordinate of the cursor does not change. |
*/ |
extern int __console_initdll_status; |
/* == 1 if dll loaded */ |
extern dword *con_dll_ver; |
extern int con_init_console_dll(void); |
/* load library and link function symbols. returns 1 if error |
called automatic in printf, otherwise, see __console_initdll_status |
*/ |
#endif |
/programs/develop/ktcc/trunk/libc/include/kos32sys1.h |
---|
0,0 → 1,723 |
#ifndef __KOS_32_SYS_H__ |
#define __KOS_32_SYS_H__ |
// file header taken from newlib |
// added many sys functions, compatible with tcc |
//#include <newlib.h> |
//#include <stdint.h> |
#include <stddef.h> |
#include <stdarg.h> |
typedef unsigned int uint32_t; |
typedef int int32_t; |
typedef unsigned char uint8_t; |
typedef unsigned short int uint16_t; |
typedef unsigned long long uint64_t; |
#ifdef __cplusplus |
extern "C" { |
#endif |
//#ifdef CONFIG_DEBUF |
// #define DBG(format,...) printf(format,##__VA_ARGS__) |
//#else |
// #define DBG(format,...) |
//#endif |
#define TYPE_3_BORDER_WIDTH 5 |
#define WIN_STATE_MINIMIZED 0x02 |
#define WIN_STATE_ROLLED 0x04 |
typedef unsigned int color_t; |
typedef union |
{ |
uint32_t val; |
struct |
{ |
short x; |
short y; |
}xy; |
} __attribute__((packed)) pos_t ; |
typedef union |
{ |
uint32_t val; |
struct |
{ |
uint8_t state; |
uint8_t code; |
uint16_t ctrl_key; |
}in; |
}__attribute__((packed)) oskey_t ; |
typedef struct |
{ |
unsigned handle; |
unsigned io_code; |
void *input; |
int inp_size; |
void *output; |
int out_size; |
}ioctl_t; |
static inline void begin_draw(void) |
{ |
__asm__ __volatile__( |
"int $0x40" ::"a"(12),"b"(1)); |
}; |
static inline |
void end_draw(void) |
{ |
__asm__ __volatile__( |
"int $0x40" ::"a"(12),"b"(2)); |
}; |
static inline |
void sys_create_window(int x, int y, int w, int h, const char *name, |
color_t workcolor, uint32_t style) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(0), |
"b"((x << 16) | ((w-1) & 0xFFFF)), |
"c"((y << 16) | ((h-1) & 0xFFFF)), |
"d"((style << 24) | (workcolor & 0xFFFFFF)), |
"D"(name), |
"S"(0) : "memory"); |
}; |
static inline |
void define_button(uint32_t x_w, uint32_t y_h, uint32_t id, uint32_t color) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(8), |
"b"(x_w), |
"c"(y_h), |
"d"(id), |
"S"(color)); |
}; |
static inline |
void draw_line(int xs, int ys, int xe, int ye, color_t color) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(38), "d"(color), |
"b"((xs << 16) | xe), |
"c"((ys << 16) | ye)); |
} |
static inline |
void draw_bar(int x, int y, int w, int h, color_t color) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(13), "d"(color), |
"b"((x << 16) | w), |
"c"((y << 16) | h)); |
} |
static inline |
void draw_bitmap(void *bitmap, int x, int y, int w, int h) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(7), "b"(bitmap), |
"c"((w << 16) | h), |
"d"((x << 16) | y)); |
} |
static inline |
void draw_text_sys(const char *text, int x, int y, int len, color_t color) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(4),"d"(text), |
"b"((x << 16) | y), |
"S"(len),"c"(color) |
:"memory"); |
} |
static inline |
uint32_t get_skin_height(void) |
{ |
uint32_t height; |
__asm__ __volatile__( |
"int $0x40 \n\t" |
:"=a"(height) |
:"a"(48),"b"(4)); |
return height; |
}; |
/* |
static inline void BeginDraw(void) __attribute__ ((alias ("begin_draw"))); |
static inline void EndDraw(void) __attribute__ ((alias ("end_draw"))); |
static inline void DrawWindow(int x, int y, int w, int h, const char *name, |
color_t workcolor, uint32_t style) |
__attribute__ ((alias ("sys_create_window"))); |
static inline void DefineButton(void) __attribute__ ((alias ("define_button"))); |
static inline void DrawLine(int xs, int ys, int xe, int ye, color_t color) |
__attribute__ ((alias ("draw_line"))); |
static inline void DrawBar(int x, int y, int w, int h, color_t color) |
__attribute__ ((alias ("draw_bar"))); |
static inline void DrawBitmap(void *bitmap, int x, int y, int w, int h) |
__attribute__ ((alias ("draw_bitmap"))); |
static inline uint32_t GetSkinHeight(void) __attribute__ ((alias ("get_skin_height"))); |
*/ |
#define POS_SCREEN 0 |
#define POS_WINDOW 1 |
static inline |
pos_t get_mouse_pos(int origin) |
{ |
pos_t val; |
__asm__ __volatile__( |
"int $0x40 \n\t" |
"rol $16, %%eax" |
:"=a"(val) |
:"a"(37),"b"(origin)); |
return val; |
} |
static inline |
uint32_t get_mouse_buttons(void) |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(37),"b"(2)); |
return val; |
}; |
static inline |
uint32_t get_mouse_wheels(void) |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40 \n\t" |
:"=a"(val) |
:"a"(37),"b"(7)); |
return val; |
}; |
static inline uint32_t load_cursor(void *path, uint32_t flags) |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(37), "b"(4), "c"(path), "d"(flags)); |
return val; |
} |
static inline uint32_t set_cursor(uint32_t cursor) |
{ |
uint32_t old; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(old) |
:"a"(37), "b"(5), "c"(cursor)); |
return old; |
}; |
static inline int destroy_cursor(uint32_t cursor) |
{ |
int ret; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(ret) |
:"a"(37), "b"(6), "c"(cursor) |
:"memory"); |
return ret; |
}; |
/* |
static inline pos_t GetMousePos(int origin) __attribute__ ((alias ("get_mouse_pos"))); |
static inline uint32_t GetMouseButtons(void) __attribute__ ((alias ("get_mouse_buttons"))); |
static inline uint32_t GetMouseWheels(void) __attribute__ ((alias ("get_mouse_wheels"))); |
static inline uint32_t LoadCursor(void *path, uint32_t flags) __attribute__ ((alias ("load_cursor"))); |
static inline uint32_t SetCursor(uint32_t cursor) __attribute__ ((alias ("set_cursor"))); |
static inline int DestroyCursor(uint32_t cursor) __attribute__ ((alias ("destroy_cursor"))); |
*/ |
static inline |
uint32_t wait_for_event(uint32_t time) |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(23), "b"(time)); |
return val; |
}; |
static inline uint32_t check_os_event() |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(11)); |
return val; |
}; |
static inline uint32_t get_os_event() |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(10)); |
return val; |
}; |
//static inline uint32_t GetOsEvent(void) __attribute__ ((alias ("get_os_event"))); |
static inline |
uint32_t get_tick_count(void) |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(26),"b"(9)); |
return val; |
}; |
static inline |
uint64_t get_ns_count(void) |
{ |
uint64_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=A"(val) |
:"a"(26), "b"(10)); |
return val; |
}; |
static inline |
oskey_t get_key(void) |
{ |
oskey_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(2)); |
return val; |
} |
static inline |
uint32_t get_os_button() |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(17)); |
return val>>8; |
}; |
static inline uint32_t get_service(char *name) |
{ |
uint32_t retval = 0; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(retval) |
:"a"(68),"b"(16),"c"(name) |
:"memory"); |
return retval; |
}; |
static inline int call_service(ioctl_t *io) |
{ |
int retval; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(retval) |
:"a"(68),"b"(17),"c"(io) |
:"memory","cc"); |
return retval; |
}; |
static inline void yield(void) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(68), "b"(1)); |
}; |
static inline void delay(uint32_t time) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(5), "b"(time) |
:"memory"); |
}; |
static inline |
void *user_alloc(size_t size) |
{ |
void *val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(68),"b"(12),"c"(size)); |
return val; |
} |
static inline |
int user_free(void *mem) |
{ |
int val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(68),"b"(13),"c"(mem)); |
return val; |
} |
static inline |
void* user_realloc(void *mem, size_t size) |
{ |
void *val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(68),"b"(20),"c"(size),"d"(mem) |
:"memory"); |
return val; |
}; |
static inline |
int *user_unmap(void *base, size_t offset, size_t size) |
{ |
int *val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size)); |
return val; |
}; |
/* |
static inline void *UserAlloc(size_t size) __attribute__ ((alias ("user_alloc"))); |
static inline int UserFree(void *mem) __attribute__ ((alias ("user_free"))); |
static inline void* UserRealloc(void *mem, size_t size) __attribute__ ((alias ("user_realloc"))); |
static inline int *UserUnmap(void *base, size_t offset, size_t size) __attribute__ ((alias ("user_unmap"))); |
*/ |
typedef union |
{ |
struct |
{ |
void *data; |
size_t size; |
} x; |
unsigned long long raw; |
}ufile_t; |
static inline ufile_t load_file(const char *path) |
{ |
ufile_t uf; |
__asm__ __volatile__ ( |
"int $0x40" |
:"=A"(uf.raw) |
:"a" (68), "b"(27),"c"(path)); |
return uf; |
}; |
//static inline ufile_t LoadFile(const char *path) __attribute__ ((alias ("load_file"))); |
static inline int GetScreenSize() |
{ |
int retval; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(retval) |
:"a"(61), "b"(1)); |
return retval; |
} |
static inline void get_proc_info(char *info) |
{ |
__asm__ __volatile__( |
"int $0x40" |
: |
:"a"(9), "b"(info), "c"(-1) |
:"memory"); |
}; |
//static inline void GetProcInfo(char *info) __attribute__ ((alias ("get_proc_info"))); |
struct blit_call |
{ |
int dstx; |
int dsty; |
int w; |
int h; |
int srcx; |
int srcy; |
int srcw; |
int srch; |
void *bitmap; |
int stride; |
}; |
static inline void Blit(void *bitmap, int dst_x, int dst_y, |
int src_x, int src_y, int w, int h, |
int src_w, int src_h, int stride) |
{ |
volatile struct blit_call bc; |
bc.dstx = dst_x; |
bc.dsty = dst_y; |
bc.w = w; |
bc.h = h; |
bc.srcx = src_x; |
bc.srcy = src_y; |
bc.srcw = src_w; |
bc.srch = src_h; |
bc.stride = stride; |
bc.bitmap = bitmap; |
__asm__ __volatile__( |
"int $0x40" |
::"a"(73),"b"(0),"c"(&bc.dstx)); |
}; |
int create_thread(int (*proc)(void *param), void *param, int stack_size); |
void* load_library(const char *name); |
void* get_proc_address(void *handle, const char *proc_name); |
void enumerate_libraries(int (*callback)(void *handle, const char* name, |
uint32_t base, uint32_t size, void *user_data), |
void *user_data); |
// May be next section need to be added in newlibc |
enum KOLIBRI_GUI_EVENTS { |
KOLIBRI_EVENT_NONE = 0, /* Event queue is empty */ |
KOLIBRI_EVENT_REDRAW = 1, /* Window and window elements should be redrawn */ |
KOLIBRI_EVENT_KEY = 2, /* A key on the keyboard was pressed */ |
KOLIBRI_EVENT_BUTTON = 3, /* A button was clicked with the mouse */ |
KOLIBRI_EVENT_DESKTOP = 5, /* Desktop redraw finished */ |
KOLIBRI_EVENT_MOUSE = 6, /* Mouse activity (movement, button press) was detected */ |
KOLIBRI_EVENT_IPC = 7, /* Interprocess communication notify */ |
KOLIBRI_EVENT_NETWORK = 8, /* Network event */ |
KOLIBRI_EVENT_DEBUG = 9, /* Debug subsystem event */ |
KOLIBRI_EVENT_IRQBEGIN = 16 /* 16..31 IRQ0..IRQ15 interrupt =IRQBEGIN+IRQn */ |
}; |
// copied from /programs/system/shell/system/kolibri.c |
// fn's returned -1 as syserror, 1 as error, 0 as OK |
static inline |
int kol_clip_num() |
{ |
register uint32_t val; |
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(0)); |
return val; |
} |
static inline |
char* kol_clip_get(int n) |
// returned buffer must be freed by user_free() |
{ |
register char* val; |
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(1), "c"(n)); |
return val; |
} |
static inline |
int kol_clip_set(int n, char buffer[]) |
{ |
register uint32_t val; |
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(2), "c"(n), "d"(buffer)); |
return val; |
} |
static inline |
int kol_clip_pop() |
{ |
register uint32_t val; |
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(3)); |
return val; |
} |
static inline |
int kol_clip_unlock() |
{ |
register uint32_t val; |
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(4)); |
return val; |
} |
struct kolibri_system_colors { |
color_t frame_area; |
color_t grab_bar; |
color_t grab_bar_button; |
color_t grab_button_text; |
color_t grab_text; |
color_t work_area; |
color_t work_button; |
color_t work_button_text; |
color_t work_text; |
color_t work_graph; |
}; |
static inline void get_system_colors(struct kolibri_system_colors *color_table) |
{ |
__asm__ volatile ("int $0x40" |
: |
:"a"(48),"b"(3),"c"(color_table),"d"(40) |
); |
/* color_table should point to the system color table */ |
} |
static inline void debug_board_write_byte(const char ch){ |
__asm__ __volatile__( |
"int $0x40" |
: |
:"a"(63), "b"(1), "c"(ch)); |
} |
static inline void draw_number_sys(int32_t number, int x, int y, int len, color_t color){ |
register uint32_t fmt; |
fmt = len << 16 | 0x80000000; // no leading zeros + width |
// fmt = len << 16 | 0x00000000; // leading zeros + width |
__asm__ __volatile__( |
"int $0x40" |
: |
:"a"(47), "b"(fmt), "c"(number), "d"((x << 16) | y), "S"(color)); |
} |
static inline |
uint32_t get_mouse_eventstate(void) |
{ |
uint32_t val; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(val) |
:"a"(37),"b"(3)); |
return val; |
}; |
static inline |
uint32_t set_event_mask(uint32_t mask) |
{ |
register uint32_t val; |
asm volatile ("int $0x40":"=a"(val):"a"(40), "b"(mask)); |
return val; |
} |
typedef void (*thread_proc)(void*); |
static inline |
int start_thread(thread_proc proc, char* stack_top) |
{ |
register int val; |
asm volatile ("int $0x40":"=a"(val):"a"(51), "b"(1), "c"(proc), "d"(stack_top)); |
return val; |
} |
static inline |
void kos_exit() |
{ |
asm volatile ("int $0x40"::"a"(-1)); |
} |
static inline void focus_window(int slot){ |
asm volatile ("int $0x40"::"a"(18), "b"(3), "c"(slot)); |
} |
static inline int get_thread_slot(int tid){ |
register int val; |
asm volatile ("int $0x40":"=a"(val):"a"(18), "b"(21), "c"(tid)); |
return val; |
} |
static inline void set_current_folder(char* dir){ |
asm volatile ("int $0x40"::"a"(30), "b"(1), "c"(dir)); |
} |
static inline int get_current_folder(char* buf, int bufsize){ |
register int val; |
asm volatile ("int $0x40":"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize)); |
return val; |
} |
/* |
static inline char *getcwd(char *buf, size_t size) |
{ |
int rc = get_current_folder(buf, size); |
if (rc > size) |
{ |
errno = ERANGE; |
return 0; |
} |
else |
return buf; |
} |
*/ |
// end section |
//added nonstatic inline because incomfortabre stepping in in debugger |
void __attribute__ ((noinline)) debug_board_write_str(const char* str); |
void __attribute__ ((noinline)) debug_board_printf(const char *format,...); |
/* copy body to only one project file |
void __attribute__ ((noinline)) debug_board_write_str(const char* str){ |
while(*str) |
debug_board_write_byte(*str++); |
} |
void __attribute__ ((noinline)) debug_board_printf(const char *format,...) |
{ |
va_list ap; |
char log_board[300]; |
va_start (ap, format); |
vsnprintf(log_board, sizeof log_board, format, ap); |
va_end(ap); |
debug_board_write_str(log_board); |
} |
*/ |
#ifdef __cplusplus |
} |
#endif |
#endif |
/programs/develop/ktcc/trunk/libc/include/stdio.h |
---|
63,6 → 63,9 |
#define getc(a) fgetc(a) |
char * fgets ( char * str, int num, FILE * stream ); |
int putchar ( int character ); |
int putchar (int ch); |
int getchar (void); |
int puts (const char * str); |
char * gets (char * str); |
#endif |
/programs/develop/ktcc/trunk/libc/include/tcclib.h |
---|
0,0 → 1,80 |
/* Simple libc header for TCC |
* |
* Add any function you want from the libc there. This file is here |
* only for your convenience so that you do not need to put the whole |
* glibc include files on your floppy disk |
*/ |
#ifndef _TCCLIB_H |
#define _TCCLIB_H |
#include <stddef.h> |
#include <stdarg.h> |
/* stdlib.h */ |
void *calloc(size_t nmemb, size_t size); |
void *malloc(size_t size); |
void free(void *ptr); |
void *realloc(void *ptr, size_t size); |
int atoi(const char *nptr); |
long int strtol(const char *nptr, char **endptr, int base); |
unsigned long int strtoul(const char *nptr, char **endptr, int base); |
void exit(int); |
/* stdio.h */ |
typedef struct __FILE FILE; |
#define EOF (-1) |
extern FILE *stdin; |
extern FILE *stdout; |
extern FILE *stderr; |
FILE *fopen(const char *path, const char *mode); |
FILE *fdopen(int fildes, const char *mode); |
FILE *freopen(const char *path, const char *mode, FILE *stream); |
int fclose(FILE *stream); |
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); |
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream); |
int fgetc(FILE *stream); |
char *fgets(char *s, int size, FILE *stream); |
int getc(FILE *stream); |
int getchar(void); |
char *gets(char *s); |
int ungetc(int c, FILE *stream); |
int fflush(FILE *stream); |
int putchar (int c); |
int printf(const char *format, ...); |
int fprintf(FILE *stream, const char *format, ...); |
int sprintf(char *str, const char *format, ...); |
int snprintf(char *str, size_t size, const char *format, ...); |
int asprintf(char **strp, const char *format, ...); |
int dprintf(int fd, const char *format, ...); |
int vprintf(const char *format, va_list ap); |
int vfprintf(FILE *stream, const char *format, va_list ap); |
int vsprintf(char *str, const char *format, va_list ap); |
int vsnprintf(char *str, size_t size, const char *format, va_list ap); |
int vasprintf(char **strp, const char *format, va_list ap); |
int vdprintf(int fd, const char *format, va_list ap); |
void perror(const char *s); |
/* string.h */ |
char *strcat(char *dest, const char *src); |
char *strchr(const char *s, int c); |
char *strrchr(const char *s, int c); |
char *strcpy(char *dest, const char *src); |
void *memcpy(void *dest, const void *src, size_t n); |
void *memmove(void *dest, const void *src, size_t n); |
void *memset(void *s, int c, size_t n); |
char *strdup(const char *s); |
size_t strlen(const char *s); |
/* dlfcn.h */ |
#define RTLD_LAZY 0x001 |
#define RTLD_NOW 0x002 |
#define RTLD_GLOBAL 0x100 |
void *dlopen(const char *filename, int flag); |
const char *dlerror(void); |
void *dlsym(void *handle, char *symbol); |
int dlclose(void *handle); |
#endif /* _TCCLIB_H */ |
/programs/develop/ktcc/trunk/libc/stdio/conio.c |
---|
0,0 → 1,92 |
#include <conio.h> |
#include <kolibrisys.h> |
char* con_caption = "Console app"; |
extern int __argc; |
extern char** __argv; |
extern char* __path; |
dword *con_dll_ver; |
int __console_initdll_status; |
char* con_dllname="/sys/lib/console.obj"; |
struct import{ |
char *name; |
void *data; |
}; |
void stdcall (*con_init)(dword wnd_width, dword wnd_height, |
dword scr_width, dword scr_height, const char* title); |
void stdcall (*con_exit)(int bCloseWindow); |
void stdcall (*con_set_title)(const char* title); |
void stdcall (*con_write_asciiz)(const char* str); |
void stdcall (*con_write_string)(const char* str, dword length); |
int cdecl (*con_printf)(const char* format, ...); |
dword stdcall (*con_get_flags)(void); |
dword stdcall (*con_set_flags)(dword new_flags); |
int stdcall (*con_get_font_height)(void); |
int stdcall (*con_get_cursor_height)(void); |
int stdcall (*con_set_cursor_height)(int new_height); |
int stdcall (*con_getch)(void); |
word stdcall (*con_getch2)(void); |
int stdcall (*con_kbhit)(void); |
char* stdcall (*con_gets)(char* str, int n); |
char* stdcall (*con_gets2)(con_gets2_callback callback, char* str, int n); |
void stdcall (*con_cls)(); |
void stdcall (*con_get_cursor_pos)(int* px, int* py); |
void stdcall (*con_set_cursor_pos)(int x, int y); |
// don't change order in this! linked by index |
char* con_imports[] = { |
"START", "version", "con_init", "con_write_asciiz", "con_write_string", |
"con_printf", "con_exit", "con_get_flags", "con_set_flags", "con_kbhit", |
"con_getch", "con_getch2", "con_gets", "con_gets2", "con_get_font_height", |
"con_get_cursor_height", "con_set_cursor_height", "con_cls", |
"con_get_cursor_pos", "con_set_cursor_pos", |
(char*)0 |
}; |
void con_lib_link(struct import *exp, char** imports){ |
con_dll_ver = _ksys_cofflib_getproc(exp, imports[1]); |
con_init = _ksys_cofflib_getproc(exp, imports[2]); |
con_write_asciiz = _ksys_cofflib_getproc(exp, imports[3]); |
con_write_string = _ksys_cofflib_getproc(exp, imports[4]); |
con_printf = _ksys_cofflib_getproc(exp, imports[5]); |
con_exit = _ksys_cofflib_getproc(exp, imports[6]); |
con_get_flags = _ksys_cofflib_getproc(exp, imports[7]); |
con_set_flags = _ksys_cofflib_getproc(exp, imports[8]); |
con_kbhit = _ksys_cofflib_getproc(exp, imports[9]); |
con_getch = _ksys_cofflib_getproc(exp, imports[10]); |
con_getch2 = _ksys_cofflib_getproc(exp, imports[11]); |
con_gets = _ksys_cofflib_getproc(exp, imports[12]); |
con_gets2 = _ksys_cofflib_getproc(exp, imports[13]); |
con_get_font_height = _ksys_cofflib_getproc(exp, imports[14]); |
con_get_cursor_height=_ksys_cofflib_getproc(exp, imports[15]); |
con_set_cursor_height=_ksys_cofflib_getproc(exp, imports[16]); |
con_cls = _ksys_cofflib_getproc(exp, imports[17]); |
con_get_cursor_pos = _ksys_cofflib_getproc(exp, imports[18]); |
con_set_cursor_pos = _ksys_cofflib_getproc(exp, imports[19]); |
} |
int con_init_console_dll(void) |
{ |
struct import * hDll; |
if (__console_initdll_status == 1) return 0; |
if((hDll = (struct import *)_ksys_cofflib_load(con_dllname)) == 0){ |
debug_out_str("can't load lib\n"); |
return 1; |
} |
con_lib_link(hDll, con_imports); |
con_init(-1, -1, -1, -1, con_caption); //__argv[0] && __path dont work |
__console_initdll_status = 1; |
return(0); |
} |
/programs/develop/ktcc/trunk/libc/stdio/getchar.c |
---|
0,0 → 1,6 |
#include<conio.h> |
int getchar ( void ) |
{ |
return con_getch(); |
} |
/programs/develop/ktcc/trunk/libc/stdio/gets.c |
---|
0,0 → 1,8 |
#include <conio.h> |
char * gets ( char * str ) |
{ |
con_init_console_dll(); |
return con_gets(str, 80); // small, to reduce overflow risk |
} |
/programs/develop/ktcc/trunk/libc/stdio/printf.c |
---|
1,78 → 1,23 |
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <kolibrisys.h> |
#include <conio.h> |
char* dllname="/sys/lib/console.obj"; |
int console_init_status; |
char* imports[] = {"START","version","con_init","con_write_asciiz","con_printf","con_exit",NULL}; |
char* caption = "Console app"; |
extern int __argc; |
extern char** __argv; |
extern char* __path; |
dword* dll_ver; |
void stdcall (* con_init)(dword wnd_width, dword wnd_height, dword scr_width, dword scr_height, const char* title); |
void stdcall (* con_write_asciiz)(const char* string); |
void cdecl (* con_printf)(const char* format,...); |
void stdcall (* con_exit)(dword bCloseWindow); |
struct import{ |
char *name; |
void *data; |
}; |
void printf_link(struct import *exp, char** imports){ |
dll_ver = (dword*) |
_ksys_cofflib_getproc(exp, imports[1]); |
con_init = (void stdcall (*)(dword , dword, dword, dword, const char*)) |
_ksys_cofflib_getproc(exp, imports[2]); |
con_printf = (void cdecl (*)(const char*,...)) |
_ksys_cofflib_getproc(exp, imports[4]); |
con_exit = (void stdcall (*)(dword)) |
_ksys_cofflib_getproc(exp, imports[5]); |
} |
int init_console(void) |
{ |
struct import * hDll; |
if((hDll = (struct import *)_ksys_cofflib_load(dllname)) == 0){ |
debug_out_str("can't load lib\n"); |
return 1; |
} |
printf_link(hDll, imports); |
// debug_out_str("dll loaded\n"); |
con_init(-1, -1, -1, -1, caption); //__argv[0] && __path dont work |
return(0); |
} |
int printf(const char *format,...) |
{ |
int i = 0; |
int printed_simbols; |
int printed_simbols = 0; |
va_list arg; |
char simbol[]={"%s"}; |
char *s; |
va_start(arg,format); |
if (console_init_status==0) |
{ |
i=init_console(); |
console_init_status=1; |
} |
i=con_init_console_dll(); |
if (i==0) |
{ |
s=malloc(4096); |
printed_simbols=format_print(s,4096,format,arg); |
con_printf(simbol,s); |
con_write_string(s, printed_simbols); |
free(s); |
} |
return(printed_simbols); |
/programs/develop/ktcc/trunk/libc/stdio/putchar.c |
---|
1,7 → 1,14 |
#include <stdio.h> |
#include <conio.h> |
int putchar ( int ch ) |
{ |
printf("%c", ch); |
char s[2]; |
con_init_console_dll(); |
s[0] = (char)ch; |
s[1] = '\0'; |
con_write_asciiz(s); |
return ch; |
} |
/programs/develop/ktcc/trunk/libc/stdio/puts.c |
---|
0,0 → 1,11 |
#include <conio.h> |
int puts ( const char * str ) |
{ |
con_init_console_dll(); |
con_write_asciiz(str); |
con_write_asciiz("\n"); |
return 1; |
} |
/programs/develop/ktcc/trunk/readme.txt |
---|
1,12 → 1,4 |
The main file of metcc is "tcc.c". It certainly can be compiled by MinGW Studio. |
In order to compile MenuetOS program you must have start.o, metcc.exe in the same |
directory. The command line should be of type "metcc.exe program.c melibc.a -oprogram". |
In order to compile "melibc.a" you should configure paths is compile.js and run it. |
------------------------------------------------------------------------------------ |
Äëÿ êîìïèëÿöèè melibc íåîáõîäèìî çàïóñòèòü ñêðèïò libc/make.cmd |
ïî óìîë÷àíèþ ñ÷èòàåòñÿ ÷òî â ïåðåìåííîé îêðóæåíèÿ PATH ó âàñ óêàçàí ïóòü ê ïàêåòó mingw32 |
è ê àññåìáëåðó fasm. |
------------------------------------------------------------------------------------ |
Äëÿ áîëåå ïîäðîáíûõ èíñòðóêöèé îáðàùàòåñü íà ôîðóì â òåìó |
http://meos.sysbin.com/viewtopic.php?t=565&highlight=metcc |
For more help go to link above |
see |
source/readme.* |
source/changelog |
source/tcc-doc.info or .texi |
/programs/develop/ktcc/trunk/source/varargs.h |
---|
File deleted |
/programs/develop/ktcc/trunk/source/float.h |
---|
File deleted |
/programs/develop/ktcc/trunk/source/bcheck.c |
---|
File deleted |
/programs/develop/ktcc/trunk/source/start.asm |
---|
File deleted |
\ No newline at end of file |
/programs/develop/ktcc/trunk/source/tcc-doc.html |
---|
File deleted |
/programs/develop/ktcc/trunk/source/tiny_impdef.c |
---|
File deleted |
/programs/develop/ktcc/trunk/source/stddef.h |
---|
File deleted |
/programs/develop/ktcc/trunk/source/tcctest.c |
---|
File deleted |
/programs/develop/ktcc/trunk/source/stdarg.h |
---|
File deleted |
/programs/develop/ktcc/trunk/source/libtcc_test.c |
---|
File deleted |
/programs/develop/ktcc/trunk/source/stdbool.h |
---|
File deleted |
/programs/develop/ktcc/trunk/source/boundtest.c |
---|
File deleted |
/programs/develop/ktcc/trunk/source/libtcc1.c |
---|
File deleted |
/programs/develop/ktcc/trunk/source/console.asm |
---|
File deleted |
/programs/develop/ktcc/trunk/source/.gitignore |
---|
0,0 → 1,72 |
*.o |
*.a |
a.out |
*.exe |
*.log |
tcc_g |
tcc |
/*-tcc |
tc2.c |
doc |
tc3s.c |
p3.c |
tc1.c |
error.c |
i386-gen1.c |
test.out1 |
test.out1b |
test.out2 |
test.out2b |
test.out3 |
test.out3b |
web.sh |
memdebug.c |
bench |
Makefile.uClibc |
boundtest |
prog.ref |
test.ref |
test.out |
tcc-doc.html |
ideas |
tcctest.ref |
linux.tcc |
ldtest |
libtcc_test |
instr.S |
p.c |
p2.c |
tcctest[1234] |
test[1234].out |
tests/tcclib.h |
tests/tcctest.cc |
tests/weaktest.*.o.txt |
tests/tests2/fred.txt |
tests/tests2/*.exe |
tests/hello |
tests/abitest-*cc |
tests/vla_test |
.gdb_history |
tcc.1 |
tcc.pod |
config.h |
config.mak |
config.texi |
tags |
TAGS |
.DS_Store |
*.swp |
lib/x86_64 |
lib/i386 |
lib/x86_64-win32 |
lib/i386-win32 |
lib/arm |
lib/arm64 |
tcc-doc.info |
conftest* |
tiny_libmaker |
*.dSYM |
*~ |
\#* |
.#* |
win32/* |
/programs/develop/ktcc/trunk/source/.travis.yml |
---|
0,0 → 1,0 |
language: c |
/programs/develop/ktcc/trunk/source/CMakeCache.txt |
---|
0,0 → 1,266 |
# This is the CMakeCache file. |
# For build in directory: d:/VSProjects/tinycc/tinycc-mob |
# It was generated by CMake: D:/CMake/bin/cmake.exe |
# You can edit this file to change values found and used by cmake. |
# If you do not want to change any of the values, simply exit the editor. |
# If you do want to change a value, simply edit, save, and exit the editor. |
# The syntax for the file is as follows: |
# KEY:TYPE=VALUE |
# KEY is the name of a variable in the cache. |
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. |
# VALUE is the current value for the KEY. |
######################## |
# EXTERNAL cache entries |
######################## |
//Path to a program. |
CMAKE_AR:FILEPATH=D:/codeblocks-16.01/MinGW/bin/ar.exe |
//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or |
// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. |
CMAKE_BUILD_TYPE:STRING= |
//Enable/Disable color output during build. |
CMAKE_COLOR_MAKEFILE:BOOL=ON |
//C compiler |
CMAKE_C_COMPILER:FILEPATH=cl |
//Flags used by the compiler during all build types. |
CMAKE_C_FLAGS:STRING= |
//Flags used by the compiler during debug builds. |
CMAKE_C_FLAGS_DEBUG:STRING= |
//Flags used by the compiler during release builds for minimum |
// size. |
CMAKE_C_FLAGS_MINSIZEREL:STRING= |
//Flags used by the compiler during release builds. |
CMAKE_C_FLAGS_RELEASE:STRING= |
//Flags used by the compiler during release builds with debug info. |
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING= |
//Flags used by the linker. |
CMAKE_EXE_LINKER_FLAGS:STRING= |
//Flags used by the linker during debug builds. |
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= |
//Flags used by the linker during release minsize builds. |
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= |
//Flags used by the linker during release builds. |
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= |
//Flags used by the linker during Release with Debug Info builds. |
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= |
//Install path prefix, prepended onto install directories. |
CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/tcc |
//Path to a program. |
CMAKE_LINKER:FILEPATH=D:/codeblocks-16.01/MinGW/bin/ld.exe |
//Program used to build from makefiles. |
CMAKE_MAKE_PROGRAM:STRING=nmake |
//Flags used by the linker during the creation of modules. |
CMAKE_MODULE_LINKER_FLAGS:STRING= |
//Flags used by the linker during debug builds. |
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= |
//Flags used by the linker during release minsize builds. |
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= |
//Flags used by the linker during release builds. |
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= |
//Flags used by the linker during Release with Debug Info builds. |
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= |
//Path to a program. |
CMAKE_NM:FILEPATH=D:/codeblocks-16.01/MinGW/bin/nm.exe |
//Path to a program. |
CMAKE_OBJCOPY:FILEPATH=D:/codeblocks-16.01/MinGW/bin/objcopy.exe |
//Path to a program. |
CMAKE_OBJDUMP:FILEPATH=D:/codeblocks-16.01/MinGW/bin/objdump.exe |
//Value Computed by CMake |
CMAKE_PROJECT_NAME:STATIC=tcc |
//Path to a program. |
CMAKE_RANLIB:FILEPATH=D:/codeblocks-16.01/MinGW/bin/ranlib.exe |
//Flags used by the linker during the creation of dll's. |
CMAKE_SHARED_LINKER_FLAGS:STRING= |
//Flags used by the linker during debug builds. |
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= |
//Flags used by the linker during release minsize builds. |
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= |
//Flags used by the linker during release builds. |
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= |
//Flags used by the linker during Release with Debug Info builds. |
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= |
//If set, runtime paths are not added when installing shared libraries, |
// but are added when building. |
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO |
//If set, runtime paths are not added when using shared libraries. |
CMAKE_SKIP_RPATH:BOOL=NO |
//Flags used by the linker during the creation of static libraries. |
CMAKE_STATIC_LINKER_FLAGS:STRING= |
//Flags used by the linker during debug builds. |
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= |
//Flags used by the linker during release minsize builds. |
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= |
//Flags used by the linker during release builds. |
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= |
//Flags used by the linker during Release with Debug Info builds. |
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= |
//Path to a program. |
CMAKE_STRIP:FILEPATH=D:/codeblocks-16.01/MinGW/bin/strip.exe |
//If this value is on, makefiles will be generated without the |
// .SILENT directive, and all commands will be echoed to the console |
// during the make. This is useful for debugging only. With Visual |
// Studio IDE projects all commands are done without /nologo. |
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE |
//Value Computed by CMake |
tcc_BINARY_DIR:STATIC=D:/VSProjects/tinycc/tinycc-mob |
//Value Computed by CMake |
tcc_SOURCE_DIR:STATIC=D:/VSProjects/tinycc/tinycc-mob |
######################## |
# INTERNAL cache entries |
######################## |
//ADVANCED property for variable: CMAKE_AR |
CMAKE_AR-ADVANCED:INTERNAL=1 |
//This is the directory where this CMakeCache.txt was created |
CMAKE_CACHEFILE_DIR:INTERNAL=d:/VSProjects/tinycc/tinycc-mob |
//Major version of cmake used to create the current loaded cache |
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 |
//Minor version of cmake used to create the current loaded cache |
CMAKE_CACHE_MINOR_VERSION:INTERNAL=5 |
//Patch version of cmake used to create the current loaded cache |
CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 |
//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE |
CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 |
//Path to CMake executable. |
CMAKE_COMMAND:INTERNAL=D:/CMake/bin/cmake.exe |
//Path to cpack program executable. |
CMAKE_CPACK_COMMAND:INTERNAL=D:/CMake/bin/cpack.exe |
//Path to ctest program executable. |
CMAKE_CTEST_COMMAND:INTERNAL=D:/CMake/bin/ctest.exe |
//ADVANCED property for variable: CMAKE_C_COMPILER |
CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_C_FLAGS |
CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG |
CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL |
CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE |
CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO |
CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 |
//Path to cache edit program executable. |
CMAKE_EDIT_COMMAND:INTERNAL=D:/CMake/bin/cmake-gui.exe |
//Executable file format |
CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown |
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS |
CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG |
CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL |
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE |
CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO |
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 |
//Name of external makefile project generator. |
CMAKE_EXTRA_GENERATOR:INTERNAL= |
//Name of generator. |
CMAKE_GENERATOR:INTERNAL=NMake Makefiles |
//Name of generator platform. |
CMAKE_GENERATOR_PLATFORM:INTERNAL= |
//Name of generator toolset. |
CMAKE_GENERATOR_TOOLSET:INTERNAL= |
//Source directory with the top level CMakeLists.txt file for this |
// project |
CMAKE_HOME_DIRECTORY:INTERNAL=D:/VSProjects/tinycc/tinycc-mob |
//ADVANCED property for variable: CMAKE_LINKER |
CMAKE_LINKER-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_MAKE_PROGRAM |
CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS |
CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG |
CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL |
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE |
CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO |
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_NM |
CMAKE_NM-ADVANCED:INTERNAL=1 |
//number of local generators |
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_OBJCOPY |
CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_OBJDUMP |
CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_RANLIB |
CMAKE_RANLIB-ADVANCED:INTERNAL=1 |
//Path to CMake installation. |
CMAKE_ROOT:INTERNAL=D:/CMake/share/cmake-3.5 |
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS |
CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG |
CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL |
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE |
CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO |
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH |
CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_SKIP_RPATH |
CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS |
CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG |
CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL |
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE |
CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO |
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_STRIP |
CMAKE_STRIP-ADVANCED:INTERNAL=1 |
//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE |
CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 |
/programs/develop/ktcc/trunk/source/CMakeFiles/3.5.2/CMakeRCCompiler.cmake |
---|
0,0 → 1,6 |
set(CMAKE_RC_COMPILER "rc") |
set(CMAKE_RC_COMPILER_ARG1 "") |
set(CMAKE_RC_COMPILER_LOADED 1) |
set(CMAKE_RC_SOURCE_FILE_EXTENSIONS rc;RC) |
set(CMAKE_RC_OUTPUT_EXTENSION .res) |
set(CMAKE_RC_COMPILER_ENV_VAR "RC") |
/programs/develop/ktcc/trunk/source/CMakeFiles/3.5.2/CMakeSystem.cmake |
---|
0,0 → 1,15 |
set(CMAKE_HOST_SYSTEM "Windows-6.1.7601") |
set(CMAKE_HOST_SYSTEM_NAME "Windows") |
set(CMAKE_HOST_SYSTEM_VERSION "6.1.7601") |
set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64") |
set(CMAKE_SYSTEM "Windows-6.1.7601") |
set(CMAKE_SYSTEM_NAME "Windows") |
set(CMAKE_SYSTEM_VERSION "6.1.7601") |
set(CMAKE_SYSTEM_PROCESSOR "AMD64") |
set(CMAKE_CROSSCOMPILING "FALSE") |
set(CMAKE_SYSTEM_LOADED 1) |
/programs/develop/ktcc/trunk/source/CMakeFiles/3.5.2/CompilerIdC/CMakeCCompilerId.c |
---|
0,0 → 1,544 |
#ifdef __cplusplus |
# error "A C++ compiler has been selected for C." |
#endif |
#if defined(__18CXX) |
# define ID_VOID_MAIN |
#endif |
/* Version number components: V=Version, R=Revision, P=Patch |
Version date components: YYYY=Year, MM=Month, DD=Day */ |
#if defined(__INTEL_COMPILER) || defined(__ICC) |
# define COMPILER_ID "Intel" |
# if defined(_MSC_VER) |
# define SIMULATE_ID "MSVC" |
# endif |
/* __INTEL_COMPILER = VRP */ |
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) |
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) |
# if defined(__INTEL_COMPILER_UPDATE) |
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) |
# else |
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) |
# endif |
# if defined(__INTEL_COMPILER_BUILD_DATE) |
/* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ |
# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) |
# endif |
# if defined(_MSC_VER) |
/* _MSC_VER = VVRR */ |
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) |
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) |
# endif |
#elif defined(__PATHCC__) |
# define COMPILER_ID "PathScale" |
# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) |
# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) |
# if defined(__PATHCC_PATCHLEVEL__) |
# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) |
# endif |
#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) |
# define COMPILER_ID "Embarcadero" |
# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) |
# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) |
# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) |
#elif defined(__BORLANDC__) |
# define COMPILER_ID "Borland" |
/* __BORLANDC__ = 0xVRR */ |
# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) |
# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) |
#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 |
# define COMPILER_ID "Watcom" |
/* __WATCOMC__ = VVRR */ |
# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) |
# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) |
# if (__WATCOMC__ % 10) > 0 |
# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) |
# endif |
#elif defined(__WATCOMC__) |
# define COMPILER_ID "OpenWatcom" |
/* __WATCOMC__ = VVRP + 1100 */ |
# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) |
# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) |
# if (__WATCOMC__ % 10) > 0 |
# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) |
# endif |
#elif defined(__SUNPRO_C) |
# define COMPILER_ID "SunPro" |
# if __SUNPRO_C >= 0x5100 |
/* __SUNPRO_C = 0xVRRP */ |
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) |
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) |
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) |
# else |
/* __SUNPRO_CC = 0xVRP */ |
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) |
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) |
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) |
# endif |
#elif defined(__HP_cc) |
# define COMPILER_ID "HP" |
/* __HP_cc = VVRRPP */ |
# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) |
# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) |
# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) |
#elif defined(__DECC) |
# define COMPILER_ID "Compaq" |
/* __DECC_VER = VVRRTPPPP */ |
# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) |
# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) |
# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) |
#elif defined(__IBMC__) && defined(__COMPILER_VER__) |
# define COMPILER_ID "zOS" |
/* __IBMC__ = VRP */ |
# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) |
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) |
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) |
#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 |
# define COMPILER_ID "XL" |
/* __IBMC__ = VRP */ |
# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) |
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) |
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) |
#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 |
# define COMPILER_ID "VisualAge" |
/* __IBMC__ = VRP */ |
# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) |
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) |
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) |
#elif defined(__PGI) |
# define COMPILER_ID "PGI" |
# define COMPILER_VERSION_MAJOR DEC(__PGIC__) |
# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) |
# if defined(__PGIC_PATCHLEVEL__) |
# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) |
# endif |
#elif defined(_CRAYC) |
# define COMPILER_ID "Cray" |
# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) |
# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) |
#elif defined(__TI_COMPILER_VERSION__) |
# define COMPILER_ID "TI" |
/* __TI_COMPILER_VERSION__ = VVVRRRPPP */ |
# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) |
# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) |
# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) |
#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) |
# define COMPILER_ID "Fujitsu" |
#elif defined(__TINYC__) |
# define COMPILER_ID "TinyCC" |
#elif defined(__SCO_VERSION__) |
# define COMPILER_ID "SCO" |
#elif defined(__clang__) && defined(__apple_build_version__) |
# define COMPILER_ID "AppleClang" |
# if defined(_MSC_VER) |
# define SIMULATE_ID "MSVC" |
# endif |
# define COMPILER_VERSION_MAJOR DEC(__clang_major__) |
# define COMPILER_VERSION_MINOR DEC(__clang_minor__) |
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) |
# if defined(_MSC_VER) |
/* _MSC_VER = VVRR */ |
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) |
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) |
# endif |
# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) |
#elif defined(__clang__) |
# define COMPILER_ID "Clang" |
# if defined(_MSC_VER) |
# define SIMULATE_ID "MSVC" |
# endif |
# define COMPILER_VERSION_MAJOR DEC(__clang_major__) |
# define COMPILER_VERSION_MINOR DEC(__clang_minor__) |
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) |
# if defined(_MSC_VER) |
/* _MSC_VER = VVRR */ |
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) |
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) |
# endif |
#elif defined(__GNUC__) |
# define COMPILER_ID "GNU" |
# define COMPILER_VERSION_MAJOR DEC(__GNUC__) |
# if defined(__GNUC_MINOR__) |
# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) |
# endif |
# if defined(__GNUC_PATCHLEVEL__) |
# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) |
# endif |
#elif defined(_MSC_VER) |
# define COMPILER_ID "MSVC" |
/* _MSC_VER = VVRR */ |
# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) |
# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) |
# if defined(_MSC_FULL_VER) |
# if _MSC_VER >= 1400 |
/* _MSC_FULL_VER = VVRRPPPPP */ |
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) |
# else |
/* _MSC_FULL_VER = VVRRPPPP */ |
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) |
# endif |
# endif |
# if defined(_MSC_BUILD) |
# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) |
# endif |
#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) |
# define COMPILER_ID "ADSP" |
#if defined(__VISUALDSPVERSION__) |
/* __VISUALDSPVERSION__ = 0xVVRRPP00 */ |
# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) |
# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) |
# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) |
#endif |
#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) |
# define COMPILER_ID "IAR" |
#elif defined(__ARMCC_VERSION) |
# define COMPILER_ID "ARMCC" |
#if __ARMCC_VERSION >= 1000000 |
/* __ARMCC_VERSION = VRRPPPP */ |
# define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) |
# define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) |
# define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) |
#else |
/* __ARMCC_VERSION = VRPPPP */ |
# define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) |
# define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) |
# define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) |
#endif |
#elif defined(SDCC) |
# define COMPILER_ID "SDCC" |
/* SDCC = VRP */ |
# define COMPILER_VERSION_MAJOR DEC(SDCC/100) |
# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) |
# define COMPILER_VERSION_PATCH DEC(SDCC % 10) |
#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) |
# define COMPILER_ID "MIPSpro" |
# if defined(_SGI_COMPILER_VERSION) |
/* _SGI_COMPILER_VERSION = VRP */ |
# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) |
# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) |
# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) |
# else |
/* _COMPILER_VERSION = VRP */ |
# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) |
# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) |
# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) |
# endif |
/* These compilers are either not known or too old to define an |
identification macro. Try to identify the platform and guess that |
it is the native compiler. */ |
#elif defined(__sgi) |
# define COMPILER_ID "MIPSpro" |
#elif defined(__hpux) || defined(__hpua) |
# define COMPILER_ID "HP" |
#else /* unknown compiler */ |
# define COMPILER_ID "" |
#endif |
/* Construct the string literal in pieces to prevent the source from |
getting matched. Store it in a pointer rather than an array |
because some compilers will just produce instructions to fill the |
array rather than assigning a pointer to a static array. */ |
char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; |
#ifdef SIMULATE_ID |
char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; |
#endif |
#ifdef __QNXNTO__ |
char const* qnxnto = "INFO" ":" "qnxnto[]"; |
#endif |
#if defined(__CRAYXE) || defined(__CRAYXC) |
char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; |
#endif |
#define STRINGIFY_HELPER(X) #X |
#define STRINGIFY(X) STRINGIFY_HELPER(X) |
/* Identify known platforms by name. */ |
#if defined(__linux) || defined(__linux__) || defined(linux) |
# define PLATFORM_ID "Linux" |
#elif defined(__CYGWIN__) |
# define PLATFORM_ID "Cygwin" |
#elif defined(__MINGW32__) |
# define PLATFORM_ID "MinGW" |
#elif defined(__APPLE__) |
# define PLATFORM_ID "Darwin" |
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) |
# define PLATFORM_ID "Windows" |
#elif defined(__FreeBSD__) || defined(__FreeBSD) |
# define PLATFORM_ID "FreeBSD" |
#elif defined(__NetBSD__) || defined(__NetBSD) |
# define PLATFORM_ID "NetBSD" |
#elif defined(__OpenBSD__) || defined(__OPENBSD) |
# define PLATFORM_ID "OpenBSD" |
#elif defined(__sun) || defined(sun) |
# define PLATFORM_ID "SunOS" |
#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) |
# define PLATFORM_ID "AIX" |
#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) |
# define PLATFORM_ID "IRIX" |
#elif defined(__hpux) || defined(__hpux__) |
# define PLATFORM_ID "HP-UX" |
#elif defined(__HAIKU__) |
# define PLATFORM_ID "Haiku" |
#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) |
# define PLATFORM_ID "BeOS" |
#elif defined(__QNX__) || defined(__QNXNTO__) |
# define PLATFORM_ID "QNX" |
#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) |
# define PLATFORM_ID "Tru64" |
#elif defined(__riscos) || defined(__riscos__) |
# define PLATFORM_ID "RISCos" |
#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) |
# define PLATFORM_ID "SINIX" |
#elif defined(__UNIX_SV__) |
# define PLATFORM_ID "UNIX_SV" |
#elif defined(__bsdos__) |
# define PLATFORM_ID "BSDOS" |
#elif defined(_MPRAS) || defined(MPRAS) |
# define PLATFORM_ID "MP-RAS" |
#elif defined(__osf) || defined(__osf__) |
# define PLATFORM_ID "OSF1" |
#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) |
# define PLATFORM_ID "SCO_SV" |
#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) |
# define PLATFORM_ID "ULTRIX" |
#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) |
# define PLATFORM_ID "Xenix" |
#elif defined(__WATCOMC__) |
# if defined(__LINUX__) |
# define PLATFORM_ID "Linux" |
# elif defined(__DOS__) |
# define PLATFORM_ID "DOS" |
# elif defined(__OS2__) |
# define PLATFORM_ID "OS2" |
# elif defined(__WINDOWS__) |
# define PLATFORM_ID "Windows3x" |
# else /* unknown platform */ |
# define PLATFORM_ID "" |
# endif |
#else /* unknown platform */ |
# define PLATFORM_ID "" |
#endif |
/* For windows compilers MSVC and Intel we can determine |
the architecture of the compiler being used. This is because |
the compilers do not have flags that can change the architecture, |
but rather depend on which compiler is being used |
*/ |
#if defined(_WIN32) && defined(_MSC_VER) |
# if defined(_M_IA64) |
# define ARCHITECTURE_ID "IA64" |
# elif defined(_M_X64) || defined(_M_AMD64) |
# define ARCHITECTURE_ID "x64" |
# elif defined(_M_IX86) |
# define ARCHITECTURE_ID "X86" |
# elif defined(_M_ARM) |
# if _M_ARM == 4 |
# define ARCHITECTURE_ID "ARMV4I" |
# elif _M_ARM == 5 |
# define ARCHITECTURE_ID "ARMV5I" |
# else |
# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) |
# endif |
# elif defined(_M_MIPS) |
# define ARCHITECTURE_ID "MIPS" |
# elif defined(_M_SH) |
# define ARCHITECTURE_ID "SHx" |
# else /* unknown architecture */ |
# define ARCHITECTURE_ID "" |
# endif |
#elif defined(__WATCOMC__) |
# if defined(_M_I86) |
# define ARCHITECTURE_ID "I86" |
# elif defined(_M_IX86) |
# define ARCHITECTURE_ID "X86" |
# else /* unknown architecture */ |
# define ARCHITECTURE_ID "" |
# endif |
#else |
# define ARCHITECTURE_ID "" |
#endif |
/* Convert integer to decimal digit literals. */ |
#define DEC(n) \ |
('0' + (((n) / 10000000)%10)), \ |
('0' + (((n) / 1000000)%10)), \ |
('0' + (((n) / 100000)%10)), \ |
('0' + (((n) / 10000)%10)), \ |
('0' + (((n) / 1000)%10)), \ |
('0' + (((n) / 100)%10)), \ |
('0' + (((n) / 10)%10)), \ |
('0' + ((n) % 10)) |
/* Convert integer to hex digit literals. */ |
#define HEX(n) \ |
('0' + ((n)>>28 & 0xF)), \ |
('0' + ((n)>>24 & 0xF)), \ |
('0' + ((n)>>20 & 0xF)), \ |
('0' + ((n)>>16 & 0xF)), \ |
('0' + ((n)>>12 & 0xF)), \ |
('0' + ((n)>>8 & 0xF)), \ |
('0' + ((n)>>4 & 0xF)), \ |
('0' + ((n) & 0xF)) |
/* Construct a string literal encoding the version number components. */ |
#ifdef COMPILER_VERSION_MAJOR |
char const info_version[] = { |
'I', 'N', 'F', 'O', ':', |
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', |
COMPILER_VERSION_MAJOR, |
# ifdef COMPILER_VERSION_MINOR |
'.', COMPILER_VERSION_MINOR, |
# ifdef COMPILER_VERSION_PATCH |
'.', COMPILER_VERSION_PATCH, |
# ifdef COMPILER_VERSION_TWEAK |
'.', COMPILER_VERSION_TWEAK, |
# endif |
# endif |
# endif |
']','\0'}; |
#endif |
/* Construct a string literal encoding the version number components. */ |
#ifdef SIMULATE_VERSION_MAJOR |
char const info_simulate_version[] = { |
'I', 'N', 'F', 'O', ':', |
's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', |
SIMULATE_VERSION_MAJOR, |
# ifdef SIMULATE_VERSION_MINOR |
'.', SIMULATE_VERSION_MINOR, |
# ifdef SIMULATE_VERSION_PATCH |
'.', SIMULATE_VERSION_PATCH, |
# ifdef SIMULATE_VERSION_TWEAK |
'.', SIMULATE_VERSION_TWEAK, |
# endif |
# endif |
# endif |
']','\0'}; |
#endif |
/* Construct the string literal in pieces to prevent the source from |
getting matched. Store it in a pointer rather than an array |
because some compilers will just produce instructions to fill the |
array rather than assigning a pointer to a static array. */ |
char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; |
char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; |
const char* info_language_dialect_default = "INFO" ":" "dialect_default[" |
#if !defined(__STDC_VERSION__) |
"90" |
#elif __STDC_VERSION__ >= 201000L |
"11" |
#elif __STDC_VERSION__ >= 199901L |
"99" |
#else |
#endif |
"]"; |
/*--------------------------------------------------------------------------*/ |
#ifdef ID_VOID_MAIN |
void main() {} |
#else |
int main(int argc, char* argv[]) |
{ |
int require = 0; |
require += info_compiler[argc]; |
require += info_platform[argc]; |
require += info_arch[argc]; |
#ifdef COMPILER_VERSION_MAJOR |
require += info_version[argc]; |
#endif |
#ifdef SIMULATE_ID |
require += info_simulate[argc]; |
#endif |
#ifdef SIMULATE_VERSION_MAJOR |
require += info_simulate_version[argc]; |
#endif |
#if defined(__CRAYXE) || defined(__CRAYXC) |
require += info_cray[argc]; |
#endif |
require += info_language_dialect_default[argc]; |
(void)argv; |
return require; |
} |
#endif |
/programs/develop/ktcc/trunk/source/CMakeFiles/CMakeError.log |
---|
0,0 → 1,194 |
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
Compiler: cl |
Build flags: |
Id flags: |
The output was: |
Не удается найти указанный файл |
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
Compiler: cl |
Build flags: |
Id flags: -c |
The output was: |
Не удается найти указанный файл |
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
Compiler: cl |
Build flags: |
Id flags: -Aa |
The output was: |
Не удается найти указанный файл |
Checking whether the C compiler is IAR using "" did not match "IAR .+ Compiler": |
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
Compiler: cl |
Build flags: |
Id flags: |
The output was: |
Не удается найти указанный файл |
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
Compiler: cl |
Build flags: |
Id flags: -c |
The output was: |
Не удается найти указанный файл |
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
Compiler: cl |
Build flags: |
Id flags: -Aa |
The output was: |
Не удается найти указанный файл |
Checking whether the C compiler is IAR using "" did not match "IAR .+ Compiler": |
Determining if the C compiler works failed with the following output: |
Change Dir: D:/VSProjects/tinycc/tinycc-mob/CMakeFiles/CMakeTmp |
Run Build Command:"nmake" "/NOLOGO" "cmTC_c47b5\fast" |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: D:/VSProjects/MSVC2003/bin/cl.exe |
+Build flags: |
+Id flags: |
+ |
+The output was: |
+2 |
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 |
+Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. |
+ |
+CMakeCCompilerId.c |
+Microsoft (R) Incremental Linker Version 7.10.3077 |
+Copyright (C) Microsoft Corporation. All rights reserved. |
+ |
+/out:CMakeCCompilerId.exe |
+CMakeCCompilerId.obj |
+LINK : fatal error LNK1104: cannot open file 'LIBC.lib' |
+ |
+ |
+Determining if the C compiler works failed with the following output: |
+Change Dir: D:/VSProjects/tinycc/tinycc-mob/CMakeFiles/CMakeTmp |
+ |
+Run Build Command:"nmake" "/NOLOGO" "cmTC_ae0c3\fast" |
+ |
+Generator: execution of make failed. Make command was: "nmake" "/NOLOGO" "cmTC_ae0c3\fast" |
+ |
+ |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: D:/VSProjects/MSVC2003/bin/cl.exe |
+Build flags: |
+Id flags: |
+ |
+The output was: |
+2 |
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 |
+Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. |
+ |
+CMakeCCompilerId.c |
+Microsoft (R) Incremental Linker Version 7.10.3077 |
+Copyright (C) Microsoft Corporation. All rights reserved. |
+ |
+/out:CMakeCCompilerId.exe |
+CMakeCCompilerId.obj |
+LINK : fatal error LNK1104: cannot open file 'LIBC.lib' |
+ |
+ |
+Determining if the C compiler works failed with the following output: |
+Change Dir: D:/VSProjects/tinycc/tinycc-mob/CMakeFiles/CMakeTmp |
+ |
+Run Build Command:"nmake" "/NOLOGO" "cmTC_cc918\fast" |
+ |
+Generator: execution of make failed. Make command was: "nmake" "/NOLOGO" "cmTC_cc918\fast" |
+ |
+ |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: cl |
+Build flags: |
+Id flags: |
+ |
+The output was: |
+Не удается найти указанный файл |
+ |
+ |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: cl |
+Build flags: |
+Id flags: -c |
+ |
+The output was: |
+Не удается найти указанный файл |
+ |
+ |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: cl |
+Build flags: |
+Id flags: -Aa |
+ |
+The output was: |
+Не удается найти указанный файл |
+ |
+ |
+Checking whether the C compiler is IAR using "" did not match "IAR .+ Compiler": |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: cl |
+Build flags: |
+Id flags: |
+ |
+The output was: |
+Не удается найти указанный файл |
+ |
+ |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: cl |
+Build flags: |
+Id flags: -c |
+ |
+The output was: |
+Не удается найти указанный файл |
+ |
+ |
+Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. |
+Compiler: cl |
+Build flags: |
+Id flags: -Aa |
+ |
+The output was: |
+Не удается найти указанный файл |
+ |
+ |
+Checking whether the C compiler is IAR using "" did not match "IAR .+ Compiler": |
/programs/develop/ktcc/trunk/source/CMakeFiles/CMakeOutput.log |
---|
0,0 → 1,59 |
The system is: Windows - 6.1.7601 - AMD64 |
Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. |
Compiler: D:/VSProjects/MSVC2003/bin/cl.exe |
Build flags: |
Id flags: |
The output was: |
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 |
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. |
CMakeCCompilerId.c |
Microsoft (R) Incremental Linker Version 7.10.3077 |
Copyright (C) Microsoft Corporation. All rights reserved. |
/out:CMakeCCompilerId.exe |
CMakeCCompilerId.obj |
Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.exe" |
Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.obj" |
The C compiler identification is MSVC, found in "D:/VSProjects/tinycc/tinycc-mob/CMakeFiles/3.5.2/CompilerIdC/CMakeCCompilerId.exe" |
Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. |
Compiler: D:/VSProjects/MSVC2003/bin/cl.exe |
Build flags: |
Id flags: -c |
The output was: |
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 |
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. |
CMakeCCompilerId.c |
Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.obj" |
The C compiler identification is MSVC, found in "D:/VSProjects/tinycc/tinycc-mob/CMakeFiles/3.5.2/CompilerIdC/CMakeCCompilerId.obj" |
Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. |
Compiler: D:/VSProjects/MSVC2003/bin/cl.exe |
Build flags: |
Id flags: -c |
The output was: |
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 |
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. |
CMakeCCompilerId.c |
Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.obj" |
The C compiler identification is MSVC, found in "D:/VSProjects/tinycc/tinycc-mob/CMakeFiles/3.5.2/CompilerIdC/CMakeCCompilerId.obj" |
/programs/develop/ktcc/trunk/source/CMakeFiles/cmake.check_cache |
---|
0,0 → 1,0 |
# This file is generated by cmake for dependency checking of the CMakeCache.txt file |
/programs/develop/ktcc/trunk/source/CMakeLists.txt |
---|
0,0 → 1,293 |
project(tcc C) |
cmake_minimum_required(VERSION 2.6) |
enable_testing() |
# Detect native platform |
if(WIN32) |
set(BUILD_SHARED_LIBS ON) |
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM") |
set(TCC_NATIVE_TARGET "WinCE") |
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) |
set(TCC_NATIVE_TARGET "Win64") |
else() |
set(TCC_NATIVE_TARGET "Win32") |
endif() |
else() |
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") |
set(TCC_NATIVE_TARGET "ARM") |
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^armv5") |
set(TCC_ARM_VERSION_DEFAULT 5) |
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^armv6") |
set(TCC_ARM_VERSION_DEFAULT 6) |
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^armv7") |
set(TCC_ARM_VERSION_DEFAULT 7) |
else() |
set(TCC_ARM_VERSION_DEFAULT 4) |
endif() |
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) |
set(TCC_NATIVE_TARGET "x86_64") |
set(TCC_ARCH_DIR "x86_64-linux-gnu") |
else() |
set(TCC_NATIVE_TARGET "i386") |
set(TCC_ARCH_DIR "i386-linux-gnu") |
endif() |
endif() |
if(WIN32) |
set(EXE_PATH ".") |
set(TCC_LIB_PATH lib) |
set(NATIVE_LIB_PATH) |
set(DOC_PATH doc) |
else() |
set(EXE_PATH bin) |
set(TCC_LIB_PATH lib/tcc) |
set(NATIVE_LIB_PATH lib) |
set(DOC_PATH share/doc/tcc) |
endif() |
if(NOT WIN32) |
if(EXISTS /usr/lib/${TCC_ARCH_DIR}/crti.o) |
set(CONFIG_LDDIR lib/${TCC_ARCH_DIR}) |
set(CONFIG_MULTIARCHDIR ${TCC_ARCH_DIR}) |
elseif(EXISTS /usr/lib64/crti.o) |
set(CONFIG_LDDIR lib64) |
endif() |
endif() |
# Use two variables to keep CMake configuration variable names consistent |
set(TCC_BCHECK OFF CACHE BOOL "Enable bounds checking") |
set(CONFIG_TCC_BCHECK ${TCC_BCHECK}) |
set(TCC_ASSERT OFF CACHE BOOL "Enable assertions") |
set(CONFIG_TCC_ASSERT ${TCC_ASSERT}) |
set(TCC_BUILD_NATIVE ON CACHE BOOL "Build native compiler") |
set(TCC_BUILD_I386 OFF CACHE BOOL "Build i386 cross compiler") |
set(TCC_BUILD_X64 OFF CACHE BOOL "Build x86-64 cross compiler") |
set(TCC_BUILD_WIN32 OFF CACHE BOOL "Build Windows i386 cross compiler") |
set(TCC_BUILD_WIN64 OFF CACHE BOOL "Build Windows x86-64 cross compiler") |
set(TCC_BUILD_WINCE OFF CACHE BOOL "Build Windows CE cross compiler") |
set(TCC_BUILD_ARM_FPA OFF CACHE BOOL "Build arm-fpa cross compiler") |
set(TCC_BUILD_ARM_FPA_LD OFF CACHE BOOL "Build arm-fpa-ld cross compiler") |
set(TCC_BUILD_ARM_VFP OFF CACHE BOOL "Build arm-vfp cross compiler") |
set(TCC_BUILD_ARM_EABI OFF CACHE BOOL "Build ARM EABI cross compiler") |
set(TCC_BUILD_ARM_EABIHF OFF CACHE BOOL "Build ARM EABI hardware float cross compiler") |
set(TCC_BUILD_ARM OFF CACHE BOOL "Build ARM cross compiler") |
set(TCC_BUILD_C67 OFF CACHE BOOL "Build C67 cross compiler") |
set(TCC_ARM_VERSION ${TCC_ARM_VERSION_DEFAULT} CACHE STRING "ARM target CPU version") |
set_property(CACHE TCC_ARM_VERSION PROPERTY STRINGS 4 5 6 7) |
if(WIN32) |
set(CONFIG_TCCDIR ${CMAKE_INSTALL_PREFIX}) |
else() |
set(CONFIG_TCCDIR ${CMAKE_INSTALL_PREFIX}/lib/tcc) |
endif() |
file(STRINGS "VERSION" TCC_VERSION) |
list(GET TCC_VERSION 0 TCC_VERSION) |
include_directories(${CMAKE_BINARY_DIR}) |
configure_file(config.h.in config.h) |
configure_file(config.texi.in config.texi) |
# Utility variables |
set(I386_SOURCES i386-gen.c i386-asm.c i386-asm.h i386-tok.h) |
set(X86_64_SOURCES x86_64-gen.c i386-asm.c x86_64-asm.h) |
set(ARM_SOURCES arm_gen.c) |
set(LIBTCC1_I386_SOURCES lib/alloca86.S lib/alloca86-bt.S) |
set(LIBTCC1_WIN_SOURCES win32/lib/crt1.c win32/lib/wincrt1.c win32/lib/dllcrt1.c win32/lib/dllmain.c win32/lib/chkstk.S) |
if(NOT WIN32) |
set(LIBTCC1_I386_SOURCES ${LIBTCC1_I386_SOURCES} lib/bcheck.c) |
endif() |
if(WIN32) |
add_executable(tiny_impdef win32/tools/tiny_impdef.c) |
endif() |
add_executable(tiny_libmaker_32 win32/tools/tiny_libmaker.c) |
set_target_properties(tiny_libmaker_32 PROPERTIES COMPILE_DEFINITIONS TCC_TARGET_I386) |
add_executable(tiny_libmaker_64 win32/tools/tiny_libmaker.c) |
set_target_properties(tiny_libmaker_64 PROPERTIES COMPILE_DEFINITIONS TCC_TARGET_X86_64) |
macro(make_libtcc1 prefix xcc xar defs includes sources) |
set(libtcc1_prefix) |
if("${prefix}" STRGREATER "") |
set(libtcc1_prefix ${prefix}-) |
endif() |
set(libtcc1_flags -I${CMAKE_SOURCE_DIR}/include) |
foreach(i ${defs}) |
set(libtcc1_flags ${libtcc1_flags} -D${i}) |
endforeach() |
foreach(i ${includes}) |
set(libtcc1_flags ${libtcc1_flags} -I${CMAKE_SOURCE_DIR}/${i}) |
endforeach() |
set(libtcc1_objects) |
foreach(libtcc1_c lib/libtcc1.c ${sources}) |
string(REGEX MATCH "[^/]+$" libtcc1_o ${libtcc1_c}) |
string(REGEX MATCH "^[^.]+" libtcc1_o ${libtcc1_o}) |
set(libtcc1_o ${libtcc1_prefix}${libtcc1_o}.o) |
add_custom_command(OUTPUT ${libtcc1_o} |
COMMAND ${xcc} ${libtcc1_flags} -c ${CMAKE_SOURCE_DIR}/${libtcc1_c} -o ${libtcc1_o} |
DEPENDS ${xcc} ${CMAKE_SOURCE_DIR}/${libtcc1_c} |
) |
list(APPEND libtcc1_objects ${libtcc1_o}) |
endforeach() |
add_custom_command(OUTPUT ${libtcc1_prefix}libtcc1.a |
COMMAND ${xar} ${libtcc1_prefix}libtcc1.a ${libtcc1_objects} |
DEPENDS ${xar} ${libtcc1_objects} |
) |
add_custom_target(${libtcc1_prefix}libtcc1 ALL DEPENDS ${libtcc1_prefix}libtcc1.a) |
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${libtcc1_prefix}libtcc1.a |
DESTINATION ${TCC_LIB_PATH}/${prefix} RENAME libtcc1.a) |
endmacro() |
macro(make_tcc native_name cross_name cross_enabled definitions tcc_sources libtcc_ar libtcc_sources libtcc_includes) |
if (xx${native_name} STREQUAL xx${TCC_NATIVE_TARGET}) |
set(TCC_NATIVE_DEFINITIONS ${definitions}) |
if("${CONFIG_MULTIARCHDIR}" STRGREATER "") |
set(TCC_NATIVE_DEFINITIONS ${TCC_NATIVE_DEFINITIONS} CONFIG_MULTIARCHDIR="${CONFIG_MULTIARCHDIR}") |
endif() |
if("${CONFIG_LDDIR}" STRGREATER "") |
set(TCC_NATIVE_DEFINITIONS ${TCC_NATIVE_DEFINITIONS} CONFIG_LDDIR="${CONFIG_LDDIR}") |
endif() |
set(TCC_NATIVE_FLAGS) |
foreach(make_tcc_def ${TCC_NATIVE_DEFINITIONS}) |
set(TCC_NATIVE_FLAGS ${TCC_NATIVE_FLAGS} -D${make_tcc_def}) |
endforeach() |
if (TCC_BUILD_NATIVE) |
add_library(libtcc |
libtcc.c |
tccpp.c |
tccgen.c |
tccelf.c |
tccasm.c |
tccrun.c |
tcc.h |
libtcc.h |
tcctok.h |
${tcc_sources} |
) |
set_target_properties(libtcc PROPERTIES OUTPUT_NAME tcc PREFIX lib) |
if(WIN32) |
set_target_properties(libtcc PROPERTIES LINK_FLAGS "-Wl,--output-def,libtcc.def") |
endif() |
add_executable(tcc tcc.c) |
target_link_libraries(tcc libtcc) |
if(NOT WIN32) |
target_link_libraries(tcc dl) |
endif() |
install(TARGETS tcc libtcc RUNTIME DESTINATION ${EXE_PATH} LIBRARY DESTINATION ${NATIVE_LIB_PATH} ARCHIVE DESTINATION ${NATIVE_LIB_PATH}) |
set_target_properties(tcc libtcc PROPERTIES COMPILE_DEFINITIONS "${TCC_NATIVE_DEFINITIONS}") |
if("${libtcc_sources}" STRGREATER "") |
make_libtcc1("" tcc "${libtcc_ar}" "${TCC_NATIVE_DEFINITIONS}" "${libtcc_includes}" "${libtcc_sources}") |
endif() |
endif() |
elseif(${cross_enabled}) |
add_executable(${cross_name}-tcc tcc.c) |
set_target_properties(${cross_name}-tcc PROPERTIES COMPILE_DEFINITIONS "ONE_SOURCE;${definitions}") |
install(TARGETS ${cross_name}-tcc RUNTIME DESTINATION ${EXE_PATH}) |
if("${libtcc_sources}" STRGREATER "") |
make_libtcc1(${cross_name} "${cross_name}-tcc" "${libtcc_ar}" "${definitions}" "${libtcc_includes}" "${libtcc_sources}") |
endif() |
endif() |
endmacro() |
make_tcc("Win32" i386-w64-mingw32 TCC_BUILD_WIN32 |
"TCC_TARGET_I386;TCC_TARGET_PE" |
"${I386_SOURCES};tccpe.c" |
tiny_libmaker_32 "${LIBTCC1_I386_SOURCES};${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi" |
) |
make_tcc("Win64" x86_64-w64-mingw32 TCC_BUILD_WIN64 |
"TCC_TARGET_X86_64;TCC_TARGET_PE" |
"${X86_64_SOURCES};tccpe.c" |
tiny_libmaker_64 "lib/alloca86_64.S;${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi" |
) |
make_tcc("WinCE" arm-wince-mingw32ce TCC_BUILD_WINCE |
"TCC_TARGET_ARM;TCC_ARM_VERSION=${TCC_ARM_VERSION};TCC_TARGET_PE" |
"${ARM_SOURCES};tccpe.c" |
"" "" "" |
) |
make_tcc("i386" i386-linux-gnu TCC_BUILD_I386 |
TCC_TARGET_I386 |
"${I386_SOURCES}" |
tiny_libmaker_32 "${LIBTCC1_I386_SOURCES}" "" |
) |
make_tcc("x86_64" x86_64-linux-gnu TCC_BUILD_X64 |
TCC_TARGET_X86_64 |
"${X86_64_SOURCES}" |
tiny_libmaker_64 "lib/alloca86_64.S" "" |
) |
set(ARM_DEFINITIONS TCC_TARGET_ARM TCC_ARM_VERSION=${TCC_ARM_VERSION}) |
make_tcc("" arm-linux-gnueabihf TCC_BUILD_ARM_EABIHF |
"${ARM_DEFINITIONS};TCC_ARM_EABI;TCC_ARM_HARDFLOAT" |
"${ARM_SOURCES}" |
"" "" "" |
) |
make_tcc("" arm-linux-gnueabi TCC_BUILD_ARM_EABI |
"${ARM_DEFINITIONS};TCC_ARM_EABI" |
"${ARM_SOURCES}" |
"" "" "" |
) |
make_tcc("" arm-linux-fpa TCC_BUILD_ARM_FPA |
"${ARM_DEFINITIONS}" |
"${ARM_SOURCES}" |
"" "" "" |
) |
make_tcc("" arm-linux-fpa-ld TCC_BUILD_ARM_FPA_LD |
"${ARM_DEFINITIONS};LDOUBLE_SIZE=12" |
"${ARM_SOURCES}" |
"" "" "" |
) |
make_tcc("" arm-linux-gnu TCC_BUILD_ARM_VFP |
"${ARM_DEFINITIONS};TCC_ARM_VFP" |
"${ARM_SOURCES}" |
"" "" "" |
) |
make_tcc("" c67 TCC_BUILD_C67 |
TCC_TARGET_C67 |
"c67-gen.c;tcccoff.c" |
"" "" "" |
) |
add_subdirectory(tests) |
find_program(MAKEINFO NAMES makeinfo PATHS C:/MinGW/MSYS/1.0/bin) |
if(MAKEINFO) |
add_custom_command(OUTPUT tcc-doc.html |
COMMAND ${MAKEINFO} --no-split --html -o tcc-doc.html ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi |
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi |
) |
set(TCC_DOC_FILES tcc-doc.html) |
if(NOT WIN32) |
add_custom_command(OUTPUT tcc-doc.info |
COMMAND ${MAKEINFO} -o tcc-doc.info ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi |
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi |
) |
set(TCC_DOC_FILES ${TCC_DOC_FILES} tcc-doc.info) |
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tcc-doc.info DESTINATION share/info) |
endif() |
add_custom_target(tcc-doc ALL DEPENDS ${TCC_DOC_FILES}) |
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tcc-doc.html DESTINATION ${DOC_PATH}) |
endif() |
if(WIN32) |
file(GLOB WIN32_DEFS win32/lib/*.def) |
install(FILES ${WIN32_DEFS} DESTINATION lib) |
install(FILES tcclib.h DESTINATION include) |
install(DIRECTORY include/ DESTINATION include) |
install(DIRECTORY win32/include/ DESTINATION include) |
install(DIRECTORY win32/examples/ DESTINATION examples) |
install(FILES win32/tcc-win32.txt DESTINATION doc) |
install(FILES ${CMAKE_BINARY_DIR}/libtcc.def DESTINATION libtcc) |
install(FILES ${CMAKE_BINARY_DIR}/libtcc.dll.a DESTINATION libtcc RENAME libtcc.a) |
install(FILES libtcc.h DESTINATION libtcc) |
else() |
install(FILES libtcc.h tcclib.h DESTINATION include) |
install(DIRECTORY include/ DESTINATION lib/tcc/include) |
install(DIRECTORY win32/include/ DESTINATION lib/tcc/win32/include) |
install(DIRECTORY include/ DESTINATION lib/tcc/win32/include) |
endif() |
/programs/develop/ktcc/trunk/source/Changelog |
---|
0,0 → 1,520 |
Version 0.9.27: |
Licensing: |
- TinyCC partly relicensed to MIT license |
User interface: |
- define __STDC_HOSTED__ (Michael Matz, Urs Janssen) |
- added support for CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH (Andrew Aladjev |
and Urs Janssen) |
- added option -norunsrc to control argv[0] with tcc -run (James Lyon) |
- improve --with-libgcc configure help (grischka) |
- improve error message when memory is full (grischka) |
- improve wording about compiler switches in documentation (Thomas Preud'homme) |
- use GNU triplet prefix for cross compiler names (Thomas Preud'homme) |
- ignore unknown linker optimization and as-needed option (Austin English) |
Features: |
- added ABI tests with native compiler using libtcc (James Lyon) |
- added CMake build system with support for cross-compilation (James Lyon) |
- improved variable length array support (James Lyon) |
- add the possibility to use noname functions by ordinal (YX Hao) |
- add a install-strip target to install tcc (Thomas Preud'homme) |
- add runtime selection of float ABI on ARM (Thomas Preud'homme) |
- add shared lib support on x86-64 (Michael Matz) |
Platforms: |
- support Debian GNU/kfreeBSD 64bit userspace (Thomas Preud'homme) |
- fix GNU/Hurd interpreter path (Thomas Preud'homme) |
- fix configure script for FreeBSD host (Thomas Preud'homme) |
- make tcc -run work reliably on ARM by flushing caches (Thomas Preud'homme) |
- many x86-64 ABI fixes incl. XMM register passing (James Lyon) |
- improve compatibility with mingw's long double (James Lyon) |
- avoid .stabstr section name to be truncated on win32 (Roy) |
- add support for load/store of _Bool value (Thomas Preud'homme) |
- detect instruction with incorrect operands on x86-64 (Thomas Preud'homme) |
- improved relocations on ARM (Thomas Preud'homme) |
- add va_* macro implementation for ARM (Thomas Preud'homme) |
- define __ARM_EABI__, __ARMEL__ and __ARM_PCS_VFP (Thomas Preud'homme) |
- provide a runtime library for ARM (Thomas Preud'homme) |
- vastly improved support for ARM hard float calling convention |
(Thomas Preud'homme, Daniel Glöckner) |
- tcc can uses libtcc1 on ARM (Thomas Preud'homme) |
- use __fixdfdi for all float to integer conversion (grischka) |
- simplify startup code for unix platforms (grischka) |
- improve ELF generated on ARM (Thomas Preud'homme) |
- add support for thumb to ARM relocation (Thomas Preud'homme) |
- fix globbing to match MSVC on Windows (Thomas Preud'homme) |
- deprecate FPA and OABI support for ARM (Thomas Preud'homme) |
- warn about softfloat not being supported on ARM (Thomas Preud'homme) |
Bug fixes: |
- many code clean up (Urs Janssen, grischka) |
- fixes of other's patches (grischka, Ramsay Jones, Michael Matz) |
- fix documentation about __TINYC__ (Urs Janssen) |
- improve build of documentation (Urs Janssen) |
- improve build instructions (Jov) |
- switch from texi2html to makeinfo --html to build tcc-doc.html (James Lyon) |
- improve out of tree build (James Lyon) |
- improved passing and returning of struct (James Lyon) |
- fix CMake build on i386 and x86-64 (James Lyon) |
- fix i386 calling convention issue (James Lyon) |
- fix error in Windows build of tests (James Lyon) |
- fix x86-64 long double passing (James Lyon) |
- fix crash with undefined struct (grischka) |
- normalize slashes on win32 to always use backslashes (grischka) |
- use runtime function for float to int conversion on i386 (grischka) |
- improved documentation for include and lib lookup on win32 (grischka) |
- detect redefinition of function (Thomas Preud'homme) |
- detect the use of array of functions (Thomas Preud'homme) |
- detect use of enumerator with wrong enumeration (Thomas Preud'homme) |
- detect redefinition of enumerator or enumeration (Thomas Preud'homme) |
- set the user-defined library search paths first (Vittorio Giovara) |
- detect usage of incomplete types inside struct/union (Amine Najahi) |
- various macro bug fixes (Joseph Poirier) |
- avoid wrong trigger of assert on x86-64 platform (Thomas Preud'homme) |
- fix NaN comparison (Thomas Preud'homme) |
- use libtcc for static linking with runtime library (Thomas Preud'homme) |
- fix negation of 0.0 and -0.0 values (Thomas Preud'homme) |
- fix use of long long as if condition (Thomas Preud'homme) |
- disable bound check if libgcc is used (Thomas Preud'homme) |
- error out when casting to void (grischka) |
- remove circular dependency in Makefile (grischka) |
- stop preventing gcc to do strict aliasing (grischka) |
- fix Windows build of tcc (grischka) |
- build runtime library for arm cross compiler (Thomas Preud'homme) |
- fix installation of arm cross-compiler (Thomas Preud'homme) |
- add basic test for cross-compiler (Thomas Preud'homme) |
- fix failure when generating PE on x86-64 (Archidemon) |
- fix floating point unary minus and plus (Michael Matz) |
- add more tests for signed zero float (Michael Matz) |
- fix precision of double on x86-64 (Vincent Lefevre) |
- fix bound checking of argv with -run switch (Kirill Smelkov) |
- work around a wine cmd bug when building tcc on Windows (Austin English) |
- reenable some bound check tests (grischka) |
- boundtest.c lookup honors VPATH (grischka) |
- diff compared to CC in test[123]b? are now errors (grischka) |
- fix test3 on Windows (grischka) |
- prevent gcc from building (non functional) libtcc.a (grischka) |
- fix warning related to PE file generation on x86-64 (grischka) |
- stop mixing ordinary and implicit rule in Makefile (Iavael) |
- fix integer to double conversion on ARM (Thomas Preud'homme) |
- fix parameter passing of structure < 4 bytes on ARM (Thomas Preud'homme) |
- disable builtin_frame_address test on ARM due to gcc bug (Thomas Preud'homme) |
- fix initialization of struct on ARM (Thomas Preud'homme) |
- fix parameter passing of (unsigned) long long bitfield (Thomas Preud'homme) |
- improve float to integer tests (Thomas Preud'homme) |
- fix relocation of Thumb branch to ARM function (Thomas Preud'homme) |
- fix char wrong compatibility with [un]signed char (Thomas Preud'homme) |
- choose the code to compile based on target in libtcc1 (Thomas Preud'homme) |
- fix various clang warnings (Thomas Preud'homme) |
- don't hardcode tcc in Makefile for tests (Thomas Preud'homme) |
- fix relocation of __bound_init bound checking code (Thomas Preud'homme) |
- accept only one basic type for a given variable (Thomas Preud'homme) |
- fix error when using va_* with tcc using libgcc (Thomas Preud'homme) |
- support GOT32 and PLT32 reloc on the same symbol (Thomas Preud'homme) |
- fix memory leak due to symbol attributes (mingodad) |
- partially fix bound checking of argv and arge (Thomas Preud'homme) |
- fix possible dereference when getting name of symbol (grischka) |
- fix va_list type definition on x86-64 (Daniel Glöckner) |
- reduce number of scan-build false positive (mingodad) |
version 0.9.26: |
User interface: |
- -MD/-MF (automatically generate dependencies for make) |
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III) |
- -m32/-m64 to re-exec cross compiler (Henry Kroll III) |
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov) |
- new LIBTCCAPI tcc_set_options() (grischka) |
Platforms: |
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka) |
- x86-64 assembler (Frederic Feret) |
- Many improvements for ARM target (Daniel Glöckner, Thomas Preud'homme) |
- Support WinCE PE ARM (Timo VJ Lahde) |
- Support ARM hardfloat calling convention (Thomas Preud'homme) |
- Support SELinux (Security-Enhanced Linux) (Henry Kroll III) |
- Support Debian GNU/kFreeBSD kernels (Pierre Chifflier) |
- Support GNU/Hurd kernels (Thomas Preud'homme) |
- Support OSX (tcc -run only) (Milutin Jovanovic) |
- Support multiarch configuration (Thomas Preud'homme) |
- Support out-of-tree build (Akim Demaille) |
Features: |
- C99 variable length arrays (Thomas Preud'homme & Joe Soroka) |
- Asm labels for variables and functions (Thomas Preud'homme) |
- STT_GNU_IFUNC (Indirect functions as externals) (Thomas Preud'homme) |
- More tests (tests2) (Milutin Jovanovic) |
version 0.9.25: |
- first support for x86-64 target (Shinichiro Hamaji) |
- support µClibc |
- split tcc.c into tcc.h libtcc.c tccpp.c tccgen.c tcc.c |
- improved preprocess output with linenumbers and spaces preserved |
- tcc_relocate now copies code into user buffer |
- fix bitfields with non-int types and in unions |
- improve ARM cross-compiling (Daniel Glöckner) |
- link stabstr sections from multiple objects |
- better (still limited) support for multiple TCCStates |
version 0.9.24: |
- added verbosity levels -v, -vv, -vvv |
- Accept standard input as an inputstream (Hanzac Chen) |
- Support c89 compilers other than gcc (Hanzac Chen) |
- -soname linker option (Marc Andre Tanner) |
- Just warn about unknown directives, ignore quotes in #error/#warning |
- Define __STDC_VERSION__=199901L (477) |
- Switch to newer tccpe.c (includes support for resources) |
- Handle backslashes within #include/#error/#warning |
- Import changesets (part 4) 428,457,460,467: defines for openbsd etc. |
- Use _WIN32 for a windows hosted tcc and define it for the PE target, |
otherwise define __unix / __linux (Detlef Riekenberg) |
- Import changesets (part 3) 409,410: ARM EABI by Daniel Glöckner |
- Some in-between fixes: |
TCC -E no longer hangs with macro calls involving newlines. |
(next_nomacro1 now advances the read-pointer with TOK_LINEFEED) |
Global cast (int g_i = 1LL;) no longer crashes tcc. |
(nocode_wanted is initially 1, and only 0 for gen_function) |
On win32 now tcc.exe finds 'include' & 'lib' even if itself is in 'bin'. |
(new function w32_tcc_lib_path removes 'bin' if detected) |
Added quick build batch file for mingw (win32/build-tcc.bat) |
Last added case label optimization (455) produced wrong code. Reverted. |
- Import more changesets from Rob Landley's fork (part 2): |
487: Handle long long constants in gen_opic() (Rob Landley) |
484: Handle parentheses within __attribute__((...)) (Rob Landley) |
480: Remove a goto in decl_initializer_alloc (Rob Landley) |
475: Fix dereferences in inline assembly output (Joshua Phillips) |
474: Cast ptrs to ints of different sizes correctly (Joshua Phillips) |
473: Fix size of structs with empty array member (Joshua Phillips) |
470: No warning for && and || with mixed pointers/integers (Rob Landley) |
469: Fix symbol visibility problems in the linker (Vincent Pit) |
468: Allow && and || involving pointer arguments (Rob Landley) |
455: Optimize case labels with no code in between (Zdenek Pavlas) |
450: Implement alloca for x86 (grischka) |
415: Parse unicode escape sequences (Axel Liljencrantz) |
407: Add a simple va_copy() in stdarg.h (Hasso Tepper) |
400: Allow typedef names as symbols (Dave Dodge) |
- Import some changesets from Rob Landley's fork (part 1): |
462: Use LGPL with bcheck.c and il-gen.c |
458: Fix global compound literals (in unary: case '&':) (Andrew Johnson) |
456: Use return code from tcc_output_file in main() (Michael Somos) |
442: Fix indirections with function pointers (***fn)() (grischka) |
441: Fix LL left shift in libtcc1.c:__shldi3 (grischka) |
440: Pass structures and function ptrs through ?: (grischka) |
439: Keep rvalue in bit assignment (bit2 = bit1 = x) (grischka) |
438: Degrade nonportable pointer assignment to warning (grischka) |
437: Call 'saveregs()' before jumping with logical and/or/not (grischka) |
435: Put local static variables into global memory (grischka) |
432/434: Cast double and ptr to bool (grischka) |
420: Zero pad x87 tenbyte long doubles (Felix Nawothnig) |
417: Make 'sizeof' unsigned (Rob Landley) |
397: Fix save_reg for longlongs (Daniel Glöckner) |
396: Fix "invalid relocation entry" problem on ubuntu - (Bernhard Fischer) |
- ignore AS_NEEDED ld command |
- mark executable sections as executable when running in memory |
- added support for win32 wchar_t (Filip Navara) |
- segment override prefix support (Filip Navara) |
- normalized slashes in paths (Filip Navara) |
- windows style fastcall (Filip Navara) |
- support for empty input register section in asm (Filip Navara) |
- anonymous union/struct support (Filip Navara) |
- fixed parsing of function parameters |
- workaround for function pointers in conditional expressions (Dave Dodge) |
- initial '-E' option support to use the C preprocessor alone |
- discard type qualifiers when comparing function parameters (Dave Dodge) |
- Bug fix: A long long value used as a test expression ignores the |
upper 32 bits at runtime (Dave Dodge) |
- fixed multiple concatenation of PPNUM tokens (initial patch by Dave Dodge) |
- fixed multiple typedef specifiers handling |
- fixed sign extension in some type conversions (Dave Dodge) |
version 0.9.23: |
- initial PE executable format for windows version (grischka) |
- '#pragma pack' support (grischka) |
- '#include_next' support (Bernhard Fischer) |
- ignore '-pipe' option |
- added -f[no-]leading-underscore |
- preprocessor function macro parsing fix (grischka) |
version 0.9.22: |
- simple memory optimisations: kernel compilation is 30% faster |
- linker symbol definitions fixes |
- gcc 3.4 fixes |
- fixed value stack full error |
- 'packed' attribute support for variables and structure fields |
- ignore 'const' and 'volatile' in function prototypes |
- allow '_Bool' in bit fields |
version 0.9.21: |
- ARM target support (Daniel Glöckner) |
- added '-funsigned-char, '-fsigned-char' and |
'-Wimplicit-function-declaration' |
- fixed assignment of const struct in struct |
- line comment fix (reported by Bertram Felgenhauer) |
- initial TMS320C67xx target support (TK) |
- win32 configure |
- regparm() attribute |
- many built-in assembler fixes |
- added '.org', '.fill' and '.previous' assembler directives |
- '-fno-common' option |
- '-Ttext' linker option |
- section alignment fixes |
- bit fields fixes |
- do not generate code for unused inline functions |
- '-oformat' linker option. |
- added 'binary' output format. |
version 0.9.20: |
- added '-w' option |
- added '.gnu.linkonce' ELF sections support |
- fixed libc linking when running in memory (avoid 'stat' function |
errors). |
- extended '-run' option to be able to give several arguments to a C |
script. |
version 0.9.19: |
- "alacarte" linking (Dave Long) |
- simpler function call |
- more strict type checks |
- added 'const' and 'volatile' support and associated warnings |
- added -Werror, -Wunsupported, -Wwrite-strings, -Wall. |
- added __builtin_types_compatible_p() and __builtin_constant_p() |
- chars support in assembler (Dave Long) |
- .string, .globl, .section, .text, .data and .bss asm directive |
support (Dave Long) |
- man page generated from tcc-doc.texi |
- fixed macro argument substitution |
- fixed zero argument macro parsing |
- changed license to LGPL |
- added -rdynamic option support |
version 0.9.18: |
- header fix (time.h) |
- fixed inline asm without operand case |
- fixed 'default:' or 'case x:' with '}' after (incorrect C construct accepted |
by gcc) |
- added 'A' inline asm constraint. |
version 0.9.17: |
- PLT generation fix |
- tcc doc fixes (Peter Lund) |
- struct parse fix (signaled by Pedro A. Aranda Gutierrez) |
- better _Bool lvalue support (signaled by Alex Measday) |
- function parameters must be converted to pointers (signaled by Neil Brown) |
- sanitized string and character constant parsing |
- fixed comment parse (signaled by Damian M Gryski) |
- fixed macro function bug (signaled by Philippe Ribet) |
- added configure (initial patch by Mitchell N Charity) |
- added '-run' and '-v' options (initial patch by vlindos) |
- added real date report in __DATE__ and __TIME__ macros |
version 0.9.16: |
- added assembler language support |
- added GCC inline asm() support |
- fixed multiple variable definitions : uninitialized variables are |
created as COMMON symbols. |
- optimized macro processing |
- added GCC statement expressions support |
- added GCC local labels support |
- fixed array declaration in old style function parameters |
- support casts in static structure initializations |
- added various __xxx[__] keywords for GCC compatibility |
- ignore __extension__ GCC in an expression or in a type (still not perfect) |
- added '? :' GCC extension support |
version 0.9.15: |
- compilation fixes for glibc 2.2, gcc 2.95.3 and gcc 3.2. |
- FreeBSD compile fixes. Makefile patches still missing (Carl Drougge). |
- fixed file type guessing if '.' is in the path. |
- fixed tcc_compile_string() |
- add a dummy page in ELF files to fix RX/RW accesses (pageexec at |
freemail dot hu). |
version 0.9.14: |
- added #warning. error message if invalid preprocessing directive. |
- added CType structure to ease typing (faster parse). |
- suppressed secondary hash tables (faster parse). |
- rewrote parser by optimizing common cases (faster parse). |
- fixed signed long long comparisons. |
- fixed 'int a(), b();' declaration case. |
- fixed structure init without '{}'. |
- correct alignment support in structures. |
- empty structures support. |
- gcc testsuite now supported. |
- output only warning if implicit integer/pointer conversions. |
- added static bitfield init. |
version 0.9.13: |
- correct preprocessing token pasting (## operator) in all cases (added |
preprocessing number token). |
- fixed long long register spill. |
- fixed signed long long '>>'. |
- removed memory leaks. |
- better error handling : processing can continue on link errors. A |
custom callback can be added to display error messages. Most |
errors do not call exit() now. |
- ignore -O, -W, -m and -f options |
- added old style function declarations |
- added GCC __alignof__ support. |
- added GCC typeof support. |
- added GCC computed gotos support. |
- added stack backtrace in runtime error message. Improved runtime |
error position display. |
version 0.9.12: |
- more fixes for || and && handling. |
- improved '? :' type handling. |
- fixed bound checking generation with structures |
- force '#endif' to be in same file as matching '#if' |
- #include file optimization with '#ifndef #endif' construct detection |
- macro handling optimization |
- added tcc_relocate() and tcc_get_symbol() in libtcc. |
version 0.9.11: |
- stdarg.h fix for double type (thanks to Philippe Ribet). |
- correct white space characters and added MSDOS newline support. |
- fixed invalid implicit function call type declaration. |
- special macros such as __LINE__ are defined if tested with defined(). |
- fixed '!' operator with relocated address. |
- added symbol + offset relocation (fixes some static variable initializers) |
- '-l' option can be specified anywhere. '-c' option yields default |
output name. added '-r' option for relocatable output. |
- fixed '\nnn' octal parsing. |
- fixed local extern variables declarations. |
version 0.9.10: |
- fixed lvalue type when saved in local stack. |
- fixed '#include' syntax when using macros. |
- fixed '#line' bug. |
- removed size limit on strings. Unified string constants handling |
with variable declarations. |
- added correct support for '\xX' in wchar_t strings. |
- added support for bound checking in generated executables |
- fixed -I include order. |
- fixed incorrect function displayed in runtime error. |
version 0.9.9: |
- fixed preprocessor expression parsing for #if/#elif. |
- relocated debug info (.stab section). |
- relocated bounds info (.bounds section). |
- fixed cast to char of char constants ('\377' is -1 instead of 255) |
- fixed implicit cast for unary plus. |
- strings and '__func__' have now 'char[]' type instead of 'char *' |
(fixes sizeof() return value). |
- added __start_xxx and __stop_xxx symbols in linker. |
- better DLL creation support (option -shared begins to work). |
- ELF sections and hash tables are resized dynamically. |
- executables and DLLs are stripped by default. |
version 0.9.8: |
- First version of full ELF linking support (generate objects, static |
executable, dynamic executable, dynamic libraries). Dynamic library |
support is not finished (need PIC support in compiler and some |
patches in symbol exporting). |
- First version of ELF loader for object (.o) and archive (.a) files. |
- Support of simple GNU ld scripts (GROUP and FILE commands) |
- Separated runtime library and bound check code from TCC (smaller |
compiler core). |
- fixed register reload in float compare. |
- fixed implicit char/short to int casting. |
- allow array type for address of ('&') operator. |
- fixed unused || or && result. |
- added GCC style variadic macro support. |
- optimized bound checking code for array access. |
- tcc includes are now in $(prefix)/lib/tcc/include. |
- more command line options - more consistent handling of multiple |
input files. |
- added tcc man page (thanks to Cyril Bouthors). |
- uClibc Makefile update |
- converted documentation to texinfo format. |
- added developper's guide in documentation. |
version 0.9.7: |
- added library API for easy dynamic compilation (see libtcc.h - first |
draft). |
- fixed long long register spill bug. |
- fixed '? :' register spill bug. |
version 0.9.6: |
- added floating point constant propagation (fixes negative floating |
point constants bug). |
version 0.9.5: |
- uClibc patches (submitted by Alfonso Martone). |
- error reporting fix |
- added CONFIG_TCC_BCHECK to get smaller code if needed. |
version 0.9.4: |
- windows port (currently cannot use -g, -b and dll functions). |
- faster and simpler I/O handling. |
- '-D' option works in all cases. |
- preprocessor fixes (#elif and empty macro args) |
- floating point fixes |
- first code for CIL generation (does not work yet) |
version 0.9.3: |
- better and smaller code generator. |
- full ISOC99 64 bit 'long long' support. |
- full 32 bit 'float', 64 bit 'double' and 96 bit 'long double' support. |
- added '-U' option. |
- added assembly sections support. |
- even faster startup time by mmaping sections instead of mallocing them. |
- added GNUC __attribute__ keyword support (currently supports |
'section' and 'aligned' attributes). |
- added ELF file output (only usable for debugging now) |
- added debug symbol generation (STAB format). |
- added integrated runtime error analysis ('-g' option: print clear |
run time error messages instead of "Segmentation fault"). |
- added first version of tiny memory and bound checker ('-b' option). |
version 0.9.2: |
- even faster parsing. |
- various syntax parsing fixes. |
- fixed external relocation handling for variables or functions pointers. |
- better function pointers type handling. |
- can compile multiple files (-i option). |
- ANSI C bit fields are supported. |
- beginning of float/double/long double support. |
- beginning of long long support. |
version 0.9.1: |
- full ISOC99 initializers handling. |
- compound literals. |
- structures handle in assignments and as function param or return value. |
- wide chars and strings. |
- macro bug fix |
version 0.9: |
- initial version. |
/programs/develop/ktcc/trunk/source/CodingStyle |
---|
0,0 → 1,71 |
In general, use the same coding style as the surrounding code. |
However, do not make any unnecessary changes as that complicates |
the VCS (git) history and makes it harder to merge patches. So |
do not modify code just to make it conform to a coding style. |
Indentation |
Turn on a "fill tabs with spaces" option in your editor. |
Remove tabs and trailing spaces from any lines that are modified. |
Note that some files are indented with 2 spaces (when they |
have large indentation) while most are indented with 4 spaces. |
Language |
TCC is mostly implemented in C90. Do not use any non-C90 features |
that are not already in use. |
Non-C90 features currently in use, as revealed by |
./configure --extra-cflags="-std=c90 -Wpedantic": |
- long long (including "LL" constants) |
- inline |
- very long string constants |
- assignment between function pointer and 'void *' |
- "//" comments |
- empty macro arguments (DEF_ASMTEST in i386-tok.h) |
- unnamed struct and union fields (in struct Sym), a C11 feature |
Testing |
A simple "make test" is sufficient for some simple changes. However, |
before committing a change consider performing some of the following |
additional tests: |
- Build and run "make test" on several architectures. |
- Build with ./configure --enable-cross. |
- If the generation of relocations has been changed, try compiling |
with TCC and linking with GCC/Clang. If the linker has been |
modified, try compiling with GCC/Clang and linking with TCC. |
- Test with ASan/UBSan to detect memory corruption and undefined behaviour: |
make clean |
./configure |
make |
make test |
cp libtcc.a libtcc.a.hide |
make clean |
./configure --extra-cflags="-fsanitize=address,undefined -g" |
make |
cp libtcc.a.hide libtcc.a |
make test |
- Test with Valgrind to detect some uses of uninitialised values: |
make clean |
./configure |
make |
# On Intel, because Valgrind does floating-point arithmetic differently: |
( cd tests && gcc -I.. tcctest.c && valgrind -q ./a.out > test.ref ) |
make test TCC="valgrind -q --leak-check=full `pwd`/tcc -B`pwd` -I`pwd`" |
(Because of how VLAs are implemented, invalid reads are expected |
with 79_vla_continue.) |
/programs/develop/ktcc/trunk/source/Makefile |
---|
1,4 → 1,421 |
OUTFILE = ktcc.kex |
OBJS = tcc.o console.o getcwd.o |
CGLAGS =-O2 -g -Wall -mpreferred-stack-boundary=2 -march=i386 -falign-functions=0 -fno-strict-aliasing |
include Makefile_for_program |
# |
# Tiny C Compiler Makefile |
# |
TOP ?= . |
include $(TOP)/config.mak |
VPATH = $(top_srcdir) |
CPPFLAGS += -I$(TOP) # for config.h |
ifneq (-$(findstring gcc,$(CC))-,-gcc-) |
ifeq (-$(findstring clang,$(CC))-,-clang-) |
# make clang accept gnuisms in libtcc1.c |
CFLAGS+=-fheinous-gnu-extensions |
endif |
endif |
CPPFLAGS_P=$(CPPFLAGS) -DCONFIG_TCC_STATIC |
CFLAGS_P=$(CFLAGS) -pg -static |
LIBS_P= |
LDFLAGS_P=$(LDFLAGS) |
ifdef CONFIG_WIN64 |
CONFIG_WIN32=yes |
endif |
ifndef CONFIG_WIN32 |
LIBS=-lm |
ifndef CONFIG_NOLDL |
LIBS+=-ldl |
endif |
endif |
# make libtcc as static or dynamic library? |
ifdef DISABLE_STATIC |
ifndef CONFIG_WIN32 |
LIBTCC=libtcc.so.1.0 |
else |
LIBTCC=libtcc.dll |
LIBTCC_DLL=yes |
LIBTCC_EXTRA=libtcc.def libtcc.a |
endif |
LINK_LIBTCC=-Wl,-rpath,"$(libdir)" |
ifdef DISABLE_RPATH |
LINK_LIBTCC= |
endif |
else |
LIBTCC=libtcc.a |
LINK_LIBTCC= |
endif |
CONFIG_$(ARCH) = yes |
NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386 |
NATIVE_DEFINES_$(CONFIG_x86-64) += -DTCC_TARGET_X86_64 |
NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE |
NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC |
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM |
NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT |
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI |
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP |
NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64 |
NATIVE_DEFINES += $(NATIVE_DEFINES_yes) |
ifeq ($(TOP),.) |
PROGS=tcc$(EXESUF) |
I386_CROSS = i386-linux-gnu-tcc$(EXESUF) |
WIN32_CROSS = i386-win-mingw32-tcc$(EXESUF) |
WIN64_CROSS = x86_64-win-mingw32-tcc$(EXESUF) |
WINCE_CROSS = arm-win-mingw32ce-tcc$(EXESUF) |
X64_CROSS = x86_64-linux-gnu-tcc$(EXESUF) |
ARM_FPA_CROSS = arm-linux-fpa-tcc$(EXESUF) |
ARM_FPA_LD_CROSS = arm-linux-fpa-ld-tcc$(EXESUF) |
ARM_VFP_CROSS = arm-linux-gnu-tcc$(EXESUF) |
ARM_EABI_CROSS = arm-linux-gnueabi-tcc$(EXESUF) |
ARM_EABIHF_CROSS = arm-linux-gnueabihf-tcc$(EXESUF) |
ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS) |
ARM64_CROSS = arm64-tcc$(EXESUF) |
C67_CROSS = c67-tcc$(EXESUF) |
# Legacy symlinks for cross compilers |
$(I386_CROSS)_LINK = i386-tcc$(EXESUF) |
$(WIN32_CROSS)_LINK = i386-win-tcc$(EXESUF) |
$(WIN64_CROSS)_LINK = x86_64-win-tcc$(EXESUF) |
$(WINCE_CROSS)_LINK = arm-win-tcc$(EXESUF) |
$(X64_CROSS)_LINK = x86_64-tcc$(EXESUF) |
$(ARM_FPA_CROSS)_LINK = arm-fpa-tcc$(EXESUF) |
$(ARM_FPA_LD_CROSS)_LINK = arm-fpa-ld-tcc$(EXESUF) |
$(ARM_VFP_CROSS)_LINK = arm-vfp-tcc$(EXESUF) |
$(ARM_EABI_CROSS)_LINK = arm-eabi-tcc$(EXESUF) |
ifeq ($(TARGETOS),Windows) |
ifeq ($(ARCH),i386) |
PROGS:=$($(WIN32_CROSS)_LINK) |
$($(WIN32_CROSS)_LINK)_TCC = yes |
endif |
ifeq ($(ARCH),x86-64) |
PROGS:=$($(WIN64_CROSS)_LINK) |
$($(WIN64_CROSS)_LINK)_TCC = yes |
endif |
endif |
ifeq ($(TARGETOS),Linux) |
ifeq ($(ARCH),i386) |
PROGS:=$($(I386_CROSS)_LINK) |
$($(I386_CROSS)_LINK)_TCC = yes |
endif |
ifeq ($(ARCH),x86-64) |
PROGS:=$($(X64_CROSS)_LINK) |
$($(X64_CROSS)_LINK)_TCC = yes |
endif |
endif |
CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c |
CORE_FILES += tcc.h config.h libtcc.h tcctok.h |
I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h |
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c |
WIN64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h tccpe.c |
WINCE_FILES = $(CORE_FILES) arm-gen.c tccpe.c |
X86_64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h |
ARM_FILES = $(CORE_FILES) arm-gen.c |
ARM64_FILES = $(CORE_FILES) arm64-gen.c |
C67_FILES = $(CORE_FILES) c67-gen.c tcccoff.c |
ifdef CONFIG_WIN64 |
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) |
NATIVE_FILES=$(WIN64_FILES) |
PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
LIBTCC1_CROSS=lib/i386-win/libtcc1.a |
LIBTCC1=libtcc1.a |
else ifdef CONFIG_WIN32 |
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) |
NATIVE_FILES=$(WIN32_FILES) |
PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
LIBTCC1_CROSS=lib/x86_64-win/libtcc1.a |
LIBTCC1=libtcc1.a |
else ifeq ($(ARCH),i386) |
NATIVE_FILES=$(I386_FILES) |
PROGS_CROSS=$($(X64_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a \ |
lib/arm64/libtcc1.a |
LIBTCC1=libtcc1.a |
else ifeq ($(ARCH),x86-64) |
ifeq ($(TARGETOS),Darwin) |
NATIVE_FILES=$(X86_64_FILES) |
PROGS_CROSS=$($(I386_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a |
LIBTCC1=libtcc1.a |
else |
NATIVE_FILES=$(X86_64_FILES) |
PROGS_CROSS=$($(I386_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a \ |
lib/arm64/libtcc1.a |
LIBTCC1=libtcc1.a |
endif |
else ifeq ($(ARCH),arm) |
NATIVE_FILES=$(ARM_FILES) |
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
LIBTCC1=libtcc1.a |
LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a |
else ifeq ($(ARCH),arm64) |
NATIVE_FILES=$(ARM64_FILES) |
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
LIBTCC1=libtcc1.a |
LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a |
endif |
PROGS_CROSS_LINK=$(foreach PROG_CROSS,$(PROGS_CROSS),$($(PROG_CROSS)_LINK)) |
ifeq ($(TARGETOS),Darwin) |
PROGS+=tiny_libmaker$(EXESUF) |
endif |
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCC_EXTRA) |
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info |
ifdef CONFIG_CROSS |
PROGS+=$(PROGS_CROSS) |
TCCLIBS+=$(LIBTCC1_CROSS) |
endif |
all: $(PROGS) $(TCCLIBS) $(TCCDOCS) |
# Host Tiny C Compiler |
tcc$(EXESUF): tcc.o $(LIBTCC) |
$(CC) -o $@ $^ $(LIBS) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC) |
# Cross Tiny C Compilers |
%-tcc$(EXESUF): tcc.c |
$(CC) -o $@ $< -DONE_SOURCE $(if $($@_TCC),$(NATIVE_DEFINES),$(DEFINES)) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS) |
$(if $($@_LINK),ln -sf $@ $($@_LINK)) |
$(if $($@_TCC),ln -sf $@ tcc$(EXESUF)) |
# profiling version |
tcc_p$(EXESUF): $(NATIVE_FILES) |
$(CC) -o $@ $< -DONE_SOURCE $(NATIVE_DEFINES) $(CPPFLAGS_P) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P) |
$(I386_CROSS) $($(I386_CROSS)_LINK): DEFINES = -DTCC_TARGET_I386 |
$(X64_CROSS) $($(X64_CROSS)_LINK): DEFINES = -DTCC_TARGET_X86_64 |
$(WIN32_CROSS) $($(WIN32_CROSS)_LINK): DEFINES = -DTCC_TARGET_I386 -DTCC_TARGET_PE \ |
-DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ |
-DCONFIG_TCC_LIBPATHS="\"{B}/lib/32;{B}/lib\"" |
$(WIN64_CROSS) $($(WIN64_CROSS)_LINK): DEFINES = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE \ |
-DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ |
-DCONFIG_TCC_LIBPATHS="\"{B}/lib/64;{B}/lib\"" |
$(WINCE_CROSS): DEFINES = -DTCC_TARGET_PE |
$(C67_CROSS): DEFINES = -DTCC_TARGET_C67 |
$(ARM_FPA_CROSS): DEFINES = -DTCC_TARGET_ARM |
$(ARM_FPA_LD_CROSS)$(EXESUF): DEFINES = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12 |
$(ARM_VFP_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_VFP |
$(ARM_EABI_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP |
$(ARM64_CROSS): DEFINES = -DTCC_TARGET_ARM64 |
$(I386_CROSS) $($(I386_CROSS)_LINK): $(I386_FILES) |
$(X64_CROSS) $($(X64_CROSS)_LINK): $(X86_64_FILES) |
$(WIN32_CROSS) $($(WIN32_CROSS)_LINK): $(WIN32_FILES) |
$(WIN64_CROSS) $($(WIN64_CROSS)_LINK): $(WIN64_FILES) |
$(WINCE_CROSS) $($(WINCE_CROSS)_LINK): $(WINCE_FILES) |
$(C67_CROSS) $($(C67_CROSS)_LINK): $(C67_FILES) |
$(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS): $(ARM_FILES) |
$($(ARM_FPA_CROSS)_LINK) $($(ARM_FPA_LD_CROSS)_LINK) $($(ARM_VFP_CROSS)_LINK) $($(ARM_EABI_CROSS)_LINK): $(ARM_FILES) |
$(ARM64_CROSS): $(ARM64_FILES) |
# libtcc generation and test |
ifndef ONE_SOURCE |
LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES)))) |
LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES),$(NATIVE_FILES)) |
else |
LIBTCC_OBJ = libtcc.o |
LIBTCC_INC = $(NATIVE_FILES) |
libtcc.o : NATIVE_DEFINES += -DONE_SOURCE |
endif |
$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC) |
$(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CPPFLAGS) $(CFLAGS) |
ifndef LIBTCC_DLL |
libtcc.a: $(LIBTCC_OBJ) |
$(AR) rcs $@ $^ |
endif |
libtcc.so.1.0: $(LIBTCC_OBJ) |
$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS) |
libtcc.so.1.0: CFLAGS+=-fPIC |
ifdef LIBTCC_DLL |
libtcc.dll libtcc.def libtcc.a: $(LIBTCC_OBJ) |
$(CC) -shared $^ -o $@ $(LDFLAGS) -Wl,--output-def,libtcc.def,--out-implib,libtcc.a |
endif |
# windows utilities |
tiny_impdef$(EXESUF): win32/tools/tiny_impdef.c |
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) |
tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c |
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) |
# TinyCC runtime libraries |
libtcc1.a : FORCE $(PROGS) |
$(MAKE) -C lib native |
if test ! -d $(ARCH); then mkdir $(ARCH); fi |
if test ! -L $(ARCH)/$@; then ln -sf ../$@ $(ARCH)/$@; fi |
lib/%/libtcc1.a : FORCE $(PROGS_CROSS) |
$(MAKE) -C lib cross TARGET=$* |
FORCE: |
# install |
TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h |
INSTALL=install |
ifdef STRIP_BINARIES |
INSTALLBIN=$(INSTALL) -s |
else |
INSTALLBIN=$(INSTALL) |
endif |
install-strip: install |
strip $(foreach PROG,$(PROGS),"$(bindir)"/$(PROG)) |
ifndef CONFIG_WIN32 |
install: $(PROGS) $(TCCLIBS) $(TCCDOCS) |
mkdir -p "$(bindir)" |
$(INSTALLBIN) -m755 $(PROGS) "$(bindir)" |
cp -P tcc$(EXESUF) "$(bindir)" |
mkdir -p "$(mandir)/man1" |
-$(INSTALL) -m644 tcc.1 "$(mandir)/man1" |
mkdir -p "$(infodir)" |
-$(INSTALL) -m644 tcc-doc.info "$(infodir)" |
mkdir -p "$(tccdir)" |
mkdir -p "$(tccdir)/include" |
ifneq ($(LIBTCC1),) |
mkdir -p "$(tccdir)/$(ARCH)" |
$(INSTALL) -m644 $(LIBTCC1) "$(tccdir)/$(ARCH)" |
endif |
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include" |
mkdir -p "$(libdir)" |
$(INSTALL) -m644 $(LIBTCC) "$(libdir)" |
ifdef DISABLE_STATIC |
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so.1" |
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so" |
endif |
mkdir -p "$(includedir)" |
$(INSTALL) -m644 $(top_srcdir)/libtcc.h "$(includedir)" |
mkdir -p "$(docdir)" |
-$(INSTALL) -m644 tcc-doc.html "$(docdir)" |
ifdef CONFIG_CROSS |
mkdir -p "$(tccdir)/win32/lib/32" |
mkdir -p "$(tccdir)/win32/lib/64" |
mkdir -p "$(tccdir)/i386" |
mkdir -p "$(tccdir)/x86-64" |
ifneq ($(HOST_OS),Darwin) |
mkdir -p "$(tccdir)/arm64" |
$(INSTALL) -m644 lib/arm64/libtcc1.a "$(tccdir)/arm64" |
endif |
$(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386" |
$(INSTALL) -m644 lib/x86_64/libtcc1.a "$(tccdir)/x86-64" |
$(INSTALL) -m644 $(top_srcdir)/win32/lib/*.def "$(tccdir)/win32/lib" |
$(INSTALL) -m644 lib/i386-win/libtcc1.a "$(tccdir)/win32/lib/32" |
$(INSTALL) -m644 lib/x86_64-win/libtcc1.a "$(tccdir)/win32/lib/64" |
cp -r $(top_srcdir)/win32/include/. "$(tccdir)/win32/include" |
cp -r "$(tccdir)/include" "$(tccdir)/win32" |
endif |
uninstall: |
rm -fv $(foreach P,$(PROGS),"$(bindir)/$P") |
rm -fv "$(bindir)/tcc$(EXESUF)" |
rm -fv $(foreach P,$(LIBTCC1),"$(tccdir)/$P") |
rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P") |
rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info" |
rm -fv "$(libdir)/$(LIBTCC)" "$(includedir)/libtcc.h" |
rm -fv "$(libdir)/libtcc.so*" |
rm -rv "$(tccdir)" |
rm -rv "$(docdir)" |
else |
# on windows |
install: $(PROGS) $(TCCLIBS) $(TCCDOCS) |
mkdir -p "$(tccdir)" |
mkdir -p "$(tccdir)/lib" |
mkdir -p "$(tccdir)/include" |
mkdir -p "$(tccdir)/examples" |
mkdir -p "$(tccdir)/doc" |
mkdir -p "$(tccdir)/libtcc" |
$(INSTALLBIN) -m755 $(PROGS) "$(tccdir)" |
$(INSTALLBIN) -m755 tcc.exe "$(tccdir)" |
$(INSTALL) -m644 $(LIBTCC1) $(top_srcdir)/win32/lib/*.def "$(tccdir)/lib" |
cp -r $(top_srcdir)/win32/include/. "$(tccdir)/include" |
cp -r $(top_srcdir)/win32/examples/. "$(tccdir)/examples" |
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include" |
$(INSTALL) -m644 tcc-doc.html $(top_srcdir)/win32/tcc-win32.txt "$(tccdir)/doc" |
$(INSTALL) -m644 $(top_srcdir)/libtcc.h $(LIBTCC_EXTRA) "$(tccdir)/libtcc" |
$(INSTALL) -m644 $(LIBTCC) "$(tccdir)" |
ifdef CONFIG_CROSS |
mkdir -p "$(tccdir)/lib/32" |
mkdir -p "$(tccdir)/lib/64" |
-$(INSTALL) -m644 lib/i386-win/libtcc1.a "$(tccdir)/lib/32" |
-$(INSTALL) -m644 lib/x86_64-win/libtcc1.a "$(tccdir)/lib/64" |
endif |
uninstall: |
rm -rfv "$(tccdir)/*" |
endif |
# documentation and man page |
tcc-doc.html: tcc-doc.texi |
-makeinfo --no-split --html --number-sections -o $@ $< |
tcc.1: tcc-doc.texi |
-$(top_srcdir)/texi2pod.pl $< tcc.pod |
-pod2man --section=1 --center="Tiny C Compiler" --release=`cat $(top_srcdir)/VERSION` tcc.pod > $@ |
tcc-doc.info: tcc-doc.texi |
-makeinfo $< |
# in tests subdir |
export LIBTCC1 |
%est: |
$(MAKE) -C tests $@ 'PROGS_CROSS=$(PROGS_CROSS)' |
clean: |
rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.log \ |
*.exe a.out tags TAGS libtcc_test$(EXESUF) tcc$(EXESUF) |
-rm -r $(ARCH) arm64 |
ifeq ($(HOST_OS),Linux) |
-rm -r ./C: |
endif |
-rm *-tcc$(EXESUF) |
$(MAKE) -C tests $@ |
ifneq ($(LIBTCC1),) |
$(MAKE) -C lib $@ |
endif |
distclean: clean |
rm -vf config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html |
config.mak: |
@echo "Please run ./configure." |
@exit 1 |
tags: |
ctags $(top_srcdir)/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[chS] |
TAGS: |
ctags -e $(top_srcdir)/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[chS] |
# create release tarball from *current* git branch (including tcc-doc.html |
# and converting two files to CRLF) |
TCC-VERSION := tcc-$(shell cat $(top_srcdir)/VERSION) |
tar: tcc-doc.html |
mkdir $(TCC-VERSION) |
( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f ) |
cp tcc-doc.html $(TCC-VERSION) |
for f in tcc-win32.txt build-tcc.bat ; do \ |
cat win32/$$f | sed 's,\(.*\),\1\r,g' > $(TCC-VERSION)/win32/$$f ; \ |
done |
tar cjf $(TCC-VERSION).tar.bz2 $(TCC-VERSION) |
rm -rf $(TCC-VERSION) |
git reset |
.PHONY: all clean tar tags TAGS distclean install uninstall FORCE |
endif # ifeq ($(TOP),.) |
/programs/develop/ktcc/trunk/source/Makefile.kos32 |
---|
0,0 → 1,28 |
CC = kos32-gcc |
LD = kos32-ld |
SDK_DIR:= $(abspath ../../../sdk) |
LDFLAGS = -static -nostdlib -T $(SDK_DIR)/sources/newlib/static.lds |
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 |
INCLUDES= -I $(SDK_DIR)/sources/newlib/libc/include |
LIBPATH:= -L $(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib |
SOURCES = tcc.c \ |
libtcc.c \ |
$(NULL) |
OBJECTS = $(patsubst %.c, %.o, $(SOURCES)) |
default: tcc |
tcc: $(OBJECTS) |
$(LD) $(LDFLAGS) $(LIBPATH) -o tcc $(OBJECTS) -lgcc_eh -lc -lgcc -lc |
kos32-objcopy tcc -O binary |
%.o : %.c $(SOURCES) |
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< |
/programs/develop/ktcc/trunk/source/README |
---|
0,0 → 1,104 |
Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler |
----------------------------------------------------------------------- |
Features: |
-------- |
- SMALL! You can compile and execute C code everywhere, for example on |
rescue disks. |
- FAST! tcc generates optimized x86 code. No byte code |
overhead. Compile, assemble and link about 7 times faster than 'gcc |
-O0'. |
- UNLIMITED! Any C dynamic library can be used directly. TCC is |
heading torward full ISOC99 compliance. TCC can of course compile |
itself. |
- SAFE! tcc includes an optional memory and bound checker. Bound |
checked code can be mixed freely with standard code. |
- Compile and execute C source directly. No linking or assembly |
necessary. Full C preprocessor included. |
- C script supported : just add '#!/usr/local/bin/tcc -run' at the first |
line of your C source, and execute it directly from the command |
line. |
Documentation: |
------------- |
1) Installation on a i386/x86_64/arm Linux/OSX/FreeBSD host (for Windows read tcc-win32.txt) |
Note: For OSX and FreeBSD, gmake should be used instead of make. |
./configure |
make |
make test |
make install |
Alternatively, out-of-tree builds are supported: you may use different |
directories to hold build objects, kept separate from your source tree: |
mkdir _build |
cd _build |
../configure |
make |
make test |
make install |
Texi2html must be installed to compile the doc. |
By default, tcc is installed in /usr/local/bin. |
./configure --help shows configuration options. |
2) Introduction |
We assume here that you know ANSI C. Look at the example ex1.c to know |
what the programs look like. |
The include file <tcclib.h> can be used if you want a small basic libc |
include support (especially useful for floppy disks). Of course, you |
can also use standard headers, although they are slower to compile. |
You can begin your C script with '#!/usr/local/bin/tcc -run' on the first |
line and set its execute bits (chmod a+x your_script). Then, you can |
launch the C code as a shell or perl script :-) The command line |
arguments are put in 'argc' and 'argv' of the main functions, as in |
ANSI C. |
3) Examples |
ex1.c: simplest example (hello world). Can also be launched directly |
as a script: './ex1.c'. |
ex2.c: more complicated example: find a number with the four |
operations given a list of numbers (benchmark). |
ex3.c: compute fibonacci numbers (benchmark). |
ex4.c: more complicated: X11 program. Very complicated test in fact |
because standard headers are being used ! As for ex1.c, can also be launched |
directly as a script: './ex4.c'. |
ex5.c: 'hello world' with standard glibc headers. |
tcc.c: TCC can of course compile itself. Used to check the code |
generator. |
tcctest.c: auto test for TCC which tests many subtle possible bugs. Used |
when doing 'make test'. |
4) Full Documentation |
Please read tcc-doc.html to have all the features of TCC. |
Additional information is available for the Windows port in tcc-win32.txt. |
License: |
------- |
TCC is distributed under the GNU Lesser General Public License (see |
COPYING file). |
Fabrice Bellard. |
/programs/develop/ktcc/trunk/source/README.md |
---|
0,0 → 1,125 |
**TinyCC** (or tcc) is short for Tiny C Compiler. |
This a clone of the mob development repo at http://repo.or.cz/tinycc.git |
|Branch |Status | |
|------------|---------| |
|mob | [![Build Status](https://travis-ci.org/wqweto/tinycc.svg?branch=mob)](https://travis-ci.org/wqweto/tinycc) | |
|dev | [![Build Status](https://travis-ci.org/wqweto/tinycc.svg?branch=dev)](https://travis-ci.org/wqweto/tinycc) | |
### License |
Tiny C Compiler project is licensed under [LGPL](https://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License) but currently there is an effort to relicense the project under [MIT License](https://en.wikipedia.org/wiki/MIT_License). See RELICENSING file in root for current status. |
### Branch Policy |
The "dev" branch is the one where all contributions will be merged before reaching "mob". If you plan to propose a patch, please commit into the "dev" branch or its own feature branch. Direct commit to "mob" are not permitted. |
### Original Fabrice Bellard readme |
``` |
Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler |
----------------------------------------------------------------------- |
Features: |
-------- |
- SMALL! You can compile and execute C code everywhere, for example on |
rescue disks. |
- FAST! tcc generates optimized x86 code. No byte code |
overhead. Compile, assemble and link about 7 times faster than 'gcc |
-O0'. |
- UNLIMITED! Any C dynamic library can be used directly. TCC is |
heading torward full ISOC99 compliance. TCC can of course compile |
itself. |
- SAFE! tcc includes an optional memory and bound checker. Bound |
checked code can be mixed freely with standard code. |
- Compile and execute C source directly. No linking or assembly |
necessary. Full C preprocessor included. |
- C script supported : just add '#!/usr/local/bin/tcc -run' at the first |
line of your C source, and execute it directly from the command |
line. |
Documentation: |
------------- |
1) Installation on a i386/x86_64/arm Linux/OSX/FreeBSD host (for Windows read tcc-win32.txt) |
Note: For OSX and FreeBSD, gmake should be used instead of make. |
./configure |
make |
make test |
make install |
Alternatively, out-of-tree builds are supported: you may use different |
directories to hold build objects, kept separate from your source tree: |
mkdir _build |
cd _build |
../configure |
make |
make test |
make install |
Texi2html must be installed to compile the doc. |
By default, tcc is installed in /usr/local/bin. |
./configure --help shows configuration options. |
2) Introduction |
We assume here that you know ANSI C. Look at the example ex1.c to know |
what the programs look like. |
The include file <tcclib.h> can be used if you want a small basic libc |
include support (especially useful for floppy disks). Of course, you |
can also use standard headers, although they are slower to compile. |
You can begin your C script with '#!/usr/local/bin/tcc -run' on the first |
line and set its execute bits (chmod a+x your_script). Then, you can |
launch the C code as a shell or perl script :-) The command line |
arguments are put in 'argc' and 'argv' of the main functions, as in |
ANSI C. |
3) Examples |
ex1.c: simplest example (hello world). Can also be launched directly |
as a script: './ex1.c'. |
ex2.c: more complicated example: find a number with the four |
operations given a list of numbers (benchmark). |
ex3.c: compute fibonacci numbers (benchmark). |
ex4.c: more complicated: X11 program. Very complicated test in fact |
because standard headers are being used ! As for ex1.c, can also be launched |
directly as a script: './ex4.c'. |
ex5.c: 'hello world' with standard glibc headers. |
tcc.c: TCC can of course compile itself. Used to check the code |
generator. |
tcctest.c: auto test for TCC which tests many subtle possible bugs. Used |
when doing 'make test'. |
4) Full Documentation |
Please read tcc-doc.html to have all the features of TCC. |
Additional information is available for the Windows port in tcc-win32.txt. |
License: |
------- |
TCC is distributed under the GNU Lesser General Public License (see |
COPYING file). |
Fabrice Bellard. |
``` |
/programs/develop/ktcc/trunk/source/RELICENSING |
---|
0,0 → 1,59 |
Relicensing TinyCC |
------------------ |
The authors listed below hereby confirm their agreement to relicense TinyCC |
including their past contributions under the following terms: |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
* of this software and associated documentation files (the "Software"), to deal |
* in the Software without restriction, including without limitation the rights |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
* copies of the Software, and to permit persons to whom the Software is |
* furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
* THE SOFTWARE. |
Author (name) I agree (YES/NO) Files/Features (optional) |
------------------------------------------------------------------------------ |
Adam Sampson YES makefiles |
Daniel Glöckner NO arm-gen.c |
Daniel Glöckner YES not arm-gen.c |
Edmund Grimley Evans YES arm64 |
Fabrice Bellard YES original author |
Frédéric Féret YES x86 64/16 bit asm |
grischka YES tccpe.c |
Henry Kroll YES |
Joe Soroka YES |
Kirill Smelkov YES |
mingodad YES |
Pip Cet YES |
Shinichiro Hamaji YES x86_64-gen.c |
Vincent Lefèvre YES |
Thomas Preud'homme YES arm-gen.c |
Timo VJ Lähde (Timppa) ? tiny_libmaker.c |
TK ? tcccoff.c c67-gen.c |
Urs Janssen YES |
waddlesplash YES |
------------------------------------------------------------------------------ |
Please add yourself to the list above (rsp. replace the question mark) |
and (after fetching the latest version) commit to the "mob" branch with |
commit message: |
Relicensing TinyCC |
Thanks. |
/programs/develop/ktcc/trunk/source/TODO |
---|
0,0 → 1,112 |
TODO list: |
Bugs: |
- fix macro substitution with nested definitions (ShangHongzhang) |
- FPU st(0) is left unclean (kwisatz haderach). Incompatible with |
optimized gcc/msc code |
- constructors |
- cast bug (Peter Wang) |
- define incomplete type if defined several times (Peter Wang). |
- test binutils/gcc compile |
- tci patch + argument. |
- see -lxxx bug (Michael Charity). |
- see transparent union pb in /urs/include/sys/socket.h |
- precise behaviour of typeof with arrays ? (__put_user macro) |
but should suffice for most cases) |
- handle '? x, y : z' in unsized variable initialization (',' is |
considered incorrectly as separator in preparser) |
- transform functions to function pointers in function parameters |
(net/ipv4/ip_output.c) |
- fix function pointer type display |
- check lcc test suite -> fix bitfield binary operations |
- check section alignment in C |
- fix invalid cast in comparison 'if (v == (int8_t)v)' |
- finish varargs.h support (gcc 3.2 testsuite issue) |
- fix static functions declared inside block |
- fix multiple unions init |
- sizeof, alignof, typeof can still generate code in some cases. |
- Fix the remaining libtcc memory leaks. |
- make libtcc fully reentrant (except for the compilation stage itself). |
- struct/union/enum definitions in nested scopes (see also Debian bug #770657) |
- __STDC_IEC_559__: float f(void) { static float x = 0.0 / 0.0; return x; } |
- preprocessor: #define Y(x) Z(x) {newline} #define X Y {newline} X(X(1)) |
Portability: |
- it is assumed that int is 32-bit and sizeof(int) == 4 |
- int is used when host or target size_t would make more sense |
- TCC handles target floating-point (fp) values using the host's fp |
arithmetic, which is simple and fast but may lead to exceptions |
and inaccuracy and wrong representations when cross-compiling |
Linking: |
- static linking does not work |
- with "-run" and libtcc, no PLT is used, so branches may be out of |
range and relocations may fail; as a result libtest fails on arm64; see: |
https://lists.gnu.org/archive/html/tinycc-devel/2015-03/msg00111.html |
Bound checking: |
- '-b' bug. |
- fix bound exit on RedHat 7.3 |
- setjmp is not supported properly in bound checking. |
- fix bound check code with '&' on local variables (currently done |
only for local arrays). |
- bound checking and float/long long/struct copy code. bound |
checking and symbol + offset optimization |
Missing features: |
- disable-asm and disable-bcheck options |
- __builtin_expect() |
- improve '-E' option. |
- atexit (Nigel Horne) |
- packed attribute |
- C99: add complex types (gcc 3.2 testsuite issue) |
- postfix compound literals (see 20010124-1.c) |
Optimizations: |
- suppress specific anonymous symbol handling |
- more parse optimizations (=even faster compilation) |
- memory alloc optimizations (=even faster compilation) |
- optimize VT_LOCAL + const |
- better local variables handling (needed for other targets) |
Not critical: |
- C99: fix multiple compound literals inits in blocks (ISOC99 |
normative example - only relevant when using gotos! -> must add |
boolean variable to tell if compound literal was already |
initialized). |
- add PowerPC or ARM code generator and improve codegen for RISC (need |
to suppress VT_LOCAL and use a base register instead). |
- interactive mode / integrated debugger |
- fix preprocessor symbol redefinition |
- add portable byte code generator and interpreter for other |
unsupported architectures. |
- C++: variable declaration in for, minimal 'class' support. |
- win32: __intxx. use resolve for bchecked malloc et al. |
check exception code (exception filter func). |
- handle void (__attribute__() *ptr)() |
- VLAs are implemented in a way that is not compatible with signals: |
http://lists.gnu.org/archive/html/tinycc-devel/2015-11/msg00018.html |
- output with -E should include spaces: #define n 0xe {newline} n+1 |
Fixed (probably): |
- bug with defines: |
#define spin_lock(lock) do { } while (0) |
#define wq_spin_lock spin_lock |
#define TEST() wq_spin_lock(a) |
- typedefs can be structure fields |
- see bugfixes.diff + improvement.diff from Daniel Glockner |
- long long constant evaluation |
- add alloca() |
- gcc '-E' option. |
- #include_next support for /usr/include/limits ? |
- function pointers/lvalues in ? : (linux kernel net/core/dev.c) |
- win32: add __stdcall, check GetModuleHandle for dlls. |
/programs/develop/ktcc/trunk/source/VERSION |
---|
1,0 → 0,0 |
0.9.23 |
0.9.26 |
/programs/develop/ktcc/trunk/source/arm-gen.c |
---|
1,7 → 1,8 |
/* |
* ARMv4 code generator for TCC |
* |
* Copyright (c) 2003 Daniel Glöckner |
* Copyright (c) 2003 Daniel Glöckner |
* Copyright (c) 2012 Thomas Preud'homme |
* |
* Based on i386-gen.c by Fabrice Bellard |
* |
20,9 → 21,23 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
#ifdef TARGET_DEFS_ONLY |
#if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP) |
#error "Currently TinyCC only supports float computation with VFP instructions" |
#endif |
/* number of available registers */ |
#ifdef TCC_ARM_VFP |
#define NB_REGS 13 |
#else |
#define NB_REGS 9 |
#endif |
#ifndef TCC_ARM_VERSION |
# define TCC_ARM_VERSION 5 |
#endif |
/* a register can belong to several classes. The classes must be |
sorted from more general to more precise (see gv2() code which does |
assumptions on it). */ |
37,6 → 52,12 |
#define RC_F1 0x0100 |
#define RC_F2 0x0200 |
#define RC_F3 0x0400 |
#ifdef TCC_ARM_VFP |
#define RC_F4 0x0800 |
#define RC_F5 0x1000 |
#define RC_F6 0x2000 |
#define RC_F7 0x4000 |
#endif |
#define RC_IRET RC_R0 /* function return: integer register */ |
#define RC_LRET RC_R1 /* function return: second integer register */ |
#define RC_FRET RC_F0 /* function return: float register */ |
52,46 → 73,55 |
TREG_F1, |
TREG_F2, |
TREG_F3, |
#ifdef TCC_ARM_VFP |
TREG_F4, |
TREG_F5, |
TREG_F6, |
TREG_F7, |
#endif |
}; |
int reg_classes[NB_REGS] = { |
/* r0 */ RC_INT | RC_R0, |
/* r1 */ RC_INT | RC_R1, |
/* r2 */ RC_INT | RC_R2, |
/* r3 */ RC_INT | RC_R3, |
/* r12 */ RC_INT | RC_R12, |
/* f0 */ RC_FLOAT | RC_F0, |
/* f1 */ RC_FLOAT | RC_F1, |
/* f2 */ RC_FLOAT | RC_F2, |
/* f3 */ RC_FLOAT | RC_F3, |
}; |
#ifdef TCC_ARM_VFP |
#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0) |
#endif |
static int two2mask(int a,int b) { |
return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); |
} |
static int regmask(int r) { |
return reg_classes[r]&~(RC_INT|RC_FLOAT); |
} |
/* return registers for function */ |
#define REG_IRET TREG_R0 /* single word int return register */ |
#define REG_LRET TREG_R1 /* second word return register (for long long) */ |
#define REG_FRET TREG_F0 /* float return register */ |
#ifdef TCC_ARM_EABI |
#define TOK___divdi3 TOK___aeabi_ldivmod |
#define TOK___moddi3 TOK___aeabi_ldivmod |
#define TOK___udivdi3 TOK___aeabi_uldivmod |
#define TOK___umoddi3 TOK___aeabi_uldivmod |
#endif |
/* defined if function parameters must be evaluated in reverse order */ |
#define INVERT_FUNC_PARAMS |
/* defined if structures are passed as pointers. Otherwise structures |
are directly pushed on stack. */ |
//#define FUNC_STRUCT_PARAM_AS_PTR |
/* #define FUNC_STRUCT_PARAM_AS_PTR */ |
/* pointer size, in bytes */ |
#define PTR_SIZE 4 |
/* long double size and alignment, in bytes */ |
#ifdef TCC_ARM_VFP |
#define LDOUBLE_SIZE 8 |
#endif |
#ifndef LDOUBLE_SIZE |
#define LDOUBLE_SIZE 8 |
#endif |
#ifdef TCC_ARM_EABI |
#define LDOUBLE_ALIGN 8 |
#else |
#define LDOUBLE_ALIGN 4 |
#endif |
/* maximum alignment (for aligned attribute support) */ |
#define MAX_ALIGN 8 |
104,6 → 134,7 |
/* relocation type for 32 bit data relocation */ |
#define R_DATA_32 R_ARM_ABS32 |
#define R_DATA_PTR R_ARM_ABS32 |
#define R_JMP_SLOT R_ARM_JUMP_SLOT |
#define R_COPY R_ARM_COPY |
110,17 → 141,100 |
#define ELF_START_ADDR 0x00008000 |
#define ELF_PAGE_SIZE 0x1000 |
enum float_abi { |
ARM_SOFTFP_FLOAT, |
ARM_HARD_FLOAT, |
}; |
/******************************************************/ |
static unsigned long func_sub_sp_offset,last_itod_magic; |
#else /* ! TARGET_DEFS_ONLY */ |
/******************************************************/ |
#include "tcc.h" |
void o(unsigned long i) |
enum float_abi float_abi; |
ST_DATA const int reg_classes[NB_REGS] = { |
/* r0 */ RC_INT | RC_R0, |
/* r1 */ RC_INT | RC_R1, |
/* r2 */ RC_INT | RC_R2, |
/* r3 */ RC_INT | RC_R3, |
/* r12 */ RC_INT | RC_R12, |
/* f0 */ RC_FLOAT | RC_F0, |
/* f1 */ RC_FLOAT | RC_F1, |
/* f2 */ RC_FLOAT | RC_F2, |
/* f3 */ RC_FLOAT | RC_F3, |
#ifdef TCC_ARM_VFP |
/* d4/s8 */ RC_FLOAT | RC_F4, |
/* d5/s10 */ RC_FLOAT | RC_F5, |
/* d6/s12 */ RC_FLOAT | RC_F6, |
/* d7/s14 */ RC_FLOAT | RC_F7, |
#endif |
}; |
static int func_sub_sp_offset, last_itod_magic; |
static int leaffunc; |
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
static CType float_type, double_type, func_float_type, func_double_type; |
ST_FUNC void arm_init(struct TCCState *s) |
{ |
float_type.t = VT_FLOAT; |
double_type.t = VT_DOUBLE; |
func_float_type.t = VT_FUNC; |
func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); |
func_double_type.t = VT_FUNC; |
func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); |
float_abi = s->float_abi; |
#ifndef TCC_ARM_HARDFLOAT |
tcc_warning("soft float ABI currently not supported: default to softfp"); |
#endif |
} |
#else |
#define func_float_type func_old_type |
#define func_double_type func_old_type |
#define func_ldouble_type func_old_type |
ST_FUNC void arm_init(struct TCCState *s) |
{ |
#if !defined (TCC_ARM_VFP) |
tcc_warning("Support for FPA is deprecated and will be removed in next" |
" release"); |
#endif |
#if !defined (TCC_ARM_EABI) |
tcc_warning("Support for OABI is deprecated and will be removed in next" |
" release"); |
#endif |
} |
#endif |
static int two2mask(int a,int b) { |
return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); |
} |
static int regmask(int r) { |
return reg_classes[r]&~(RC_INT|RC_FLOAT); |
} |
/******************************************************/ |
#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) |
char *default_elfinterp(struct TCCState *s) |
{ |
if (s->float_abi == ARM_HARD_FLOAT) |
return "/lib/ld-linux-armhf.so.3"; |
else |
return "/lib/ld-linux.so.3"; |
} |
#endif |
void o(uint32_t i) |
{ |
/* this is a good place to start adding big-endian support*/ |
int ind1; |
ind1 = ind + 4; |
if (!cur_text_section) |
error("compiler error! This happens f.ex. if the compiler\n" |
tcc_error("compiler error! This happens f.ex. if the compiler\n" |
"can't evaluate constant expressions outside of a function."); |
if (ind1 > cur_text_section->data_allocated) |
section_realloc(cur_text_section, ind1); |
133,10 → 247,10 |
cur_text_section->data[ind++] = i; |
} |
static unsigned long stuff_const(unsigned long op,unsigned long c) |
static uint32_t stuff_const(uint32_t op, uint32_t c) |
{ |
int try_neg=0; |
unsigned long nc = 0,negop = 0; |
uint32_t nc = 0, negop = 0; |
switch(op&0x1F00000) |
{ |
170,7 → 284,7 |
break; |
} |
do { |
unsigned long m; |
uint32_t m; |
int i; |
if(c<256) /* catch undefined <<32 */ |
return op|c; |
187,13 → 301,13 |
//only add,sub |
void stuff_const_harder(unsigned long op,unsigned long v) { |
unsigned long x; |
void stuff_const_harder(uint32_t op, uint32_t v) { |
uint32_t x; |
x=stuff_const(op,v); |
if(x) |
o(x); |
else { |
unsigned long a[16],nv,no,o2,n2; |
uint32_t a[16], nv, no, o2, n2; |
int i,j,k; |
a[0]=0xff; |
o2=(op&0xfff0ffff)|((op&0xf000)<<4);; |
200,7 → 314,7 |
for(i=1;i<16;i++) |
a[i]=(a[i-1]>>2)|(a[i-1]<<30); |
for(i=0;i<12;i++) |
for(j=i+4;i<13+i;i++) |
for(j=i<4?i+12:15;j>=i+4;j--) |
if((v&(a[i]|a[j]))==v) { |
o(stuff_const(op,v&a[i])); |
o(stuff_const(o2,v&a[j])); |
210,7 → 324,7 |
n2=o2^0xC00000; |
nv=-v; |
for(i=0;i<12;i++) |
for(j=i+4;i<13+i;i++) |
for(j=i<4?i+12:15;j>=i+4;j--) |
if((nv&(a[i]|a[j]))==nv) { |
o(stuff_const(no,nv&a[i])); |
o(stuff_const(n2,nv&a[j])); |
217,8 → 331,8 |
return; |
} |
for(i=0;i<8;i++) |
for(j=i+4;i<12;i++) |
for(k=j+4;k<13+i;i++) |
for(j=i+4;j<12;j++) |
for(k=i<4?i+12:15;k>=j+4;k--) |
if((v&(a[i]|a[j]|a[k]))==v) { |
o(stuff_const(op,v&a[i])); |
o(stuff_const(o2,v&a[j])); |
228,8 → 342,8 |
no=op^0xC00000; |
nv=-v; |
for(i=0;i<8;i++) |
for(j=i+4;i<12;i++) |
for(k=j+4;k<13+i;i++) |
for(j=i+4;j<12;j++) |
for(k=i<4?i+12:15;k>=j+4;k--) |
if((nv&(a[i]|a[j]|a[k]))==nv) { |
o(stuff_const(no,nv&a[i])); |
o(stuff_const(n2,nv&a[j])); |
243,13 → 357,13 |
} |
} |
unsigned long encbranch(int pos,int addr,int fail) |
ST_FUNC uint32_t encbranch(int pos, int addr, int fail) |
{ |
addr-=pos+8; |
addr/=4; |
if(addr>=0x1000000 || addr<-0x1000000) { |
if(fail) |
error("FIXME: function bigger than 32MB"); |
tcc_error("FIXME: function bigger than 32MB"); |
return 0; |
} |
return 0x0A000000|(addr&0xffffff); |
258,7 → 372,7 |
int decbranch(int pos) |
{ |
int x; |
x=*(int *)(cur_text_section->data + pos); |
x=*(uint32_t *)(cur_text_section->data + pos); |
x&=0x00ffffff; |
if(x&0x800000) |
x-=0x1000000; |
268,10 → 382,10 |
/* output a symbol and patch all calls to it */ |
void gsym_addr(int t, int a) |
{ |
unsigned long *x; |
uint32_t *x; |
int lt; |
while(t) { |
x=(unsigned long *)(cur_text_section->data + t); |
x=(uint32_t *)(cur_text_section->data + t); |
t=decbranch(lt=t); |
if(a==lt+4) |
*x=0xE1A00000; // nop |
287,26 → 401,35 |
gsym_addr(t, ind); |
} |
static unsigned long fpr(int r) |
#ifdef TCC_ARM_VFP |
static uint32_t vfpr(int r) |
{ |
if(r<TREG_F0 || r>TREG_F7) |
tcc_error("compiler error! register %i is no vfp register",r); |
return r-5; |
} |
#else |
static uint32_t fpr(int r) |
{ |
if(r<TREG_F0 || r>TREG_F3) |
error("compiler error! register %i is no fp register\n",r); |
tcc_error("compiler error! register %i is no fpa register",r); |
return r-5; |
} |
#endif |
static unsigned long intr(int r) |
static uint32_t intr(int r) |
{ |
if(r==4) |
return 12; |
if((r<0 || r>4) && r!=14) |
error("compiler error! register %i is no int register\n",r); |
tcc_error("compiler error! register %i is no int register",r); |
return r; |
} |
static void calcaddr(unsigned long *base,int *off,int *sgn,int maxoff,unsigned shift) |
static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift) |
{ |
if(*off>maxoff || *off&((1<<shift)-1)) { |
unsigned long x,y; |
uint32_t x, y; |
x=0xE280E000; |
if(*sgn) |
x=0xE240E000; |
330,33 → 453,37 |
} |
} |
static unsigned long mapcc(int cc) |
static uint32_t mapcc(int cc) |
{ |
switch(cc) |
{ |
case TOK_ULT: |
return 0x30000000; |
return 0x30000000; /* CC/LO */ |
case TOK_UGE: |
return 0x20000000; |
return 0x20000000; /* CS/HS */ |
case TOK_EQ: |
return 0x00000000; |
return 0x00000000; /* EQ */ |
case TOK_NE: |
return 0x10000000; |
return 0x10000000; /* NE */ |
case TOK_ULE: |
return 0x90000000; |
return 0x90000000; /* LS */ |
case TOK_UGT: |
return 0x80000000; |
return 0x80000000; /* HI */ |
case TOK_Nset: |
return 0x40000000; /* MI */ |
case TOK_Nclear: |
return 0x50000000; /* PL */ |
case TOK_LT: |
return 0xB0000000; |
return 0xB0000000; /* LT */ |
case TOK_GE: |
return 0xA0000000; |
return 0xA0000000; /* GE */ |
case TOK_LE: |
return 0xD0000000; |
return 0xD0000000; /* LE */ |
case TOK_GT: |
return 0xC0000000; |
return 0xC0000000; /* GT */ |
} |
error("unexpected condition code"); |
return 0xE0000000; |
tcc_error("unexpected condition code"); |
return 0xE0000000; /* AL */ |
} |
static int negcc(int cc) |
375,6 → 502,10 |
return TOK_UGT; |
case TOK_UGT: |
return TOK_ULE; |
case TOK_Nset: |
return TOK_Nclear; |
case TOK_Nclear: |
return TOK_Nset; |
case TOK_LT: |
return TOK_GE; |
case TOK_GE: |
384,7 → 515,7 |
case TOK_GT: |
return TOK_LE; |
} |
error("unexpected condition code"); |
tcc_error("unexpected condition code"); |
return TOK_NE; |
} |
392,12 → 523,12 |
void load(int r, SValue *sv) |
{ |
int v, ft, fc, fr, sign; |
unsigned long op; |
uint32_t op; |
SValue v1; |
fr = sv->r; |
ft = sv->type.t; |
fc = sv->c.ul; |
fc = sv->c.i; |
if(fc>=0) |
sign=0; |
408,11 → 539,11 |
v = fr & VT_VALMASK; |
if (fr & VT_LVAL) { |
unsigned long base=0xB; // fp |
uint32_t base = 0xB; // fp |
if(v == VT_LLOCAL) { |
v1.type.t = VT_PTR; |
v1.r = VT_LOCAL | VT_LVAL; |
v1.c.ul = sv->c.ul; |
v1.c.i = sv->c.i; |
load(base=14 /* lr */, &v1); |
fc=sign=0; |
v=VT_LOCAL; |
419,7 → 550,7 |
} else if(v == VT_CONST) { |
v1.type.t = VT_PTR; |
v1.r = fr&~VT_LVAL; |
v1.c.ul = sv->c.ul; |
v1.c.i = sv->c.i; |
v1.sym=sv->sym; |
load(base=14, &v1); |
fc=sign=0; |
432,6 → 563,14 |
if(v == VT_LOCAL) { |
if(is_float(ft)) { |
calcaddr(&base,&fc,&sign,1020,2); |
#ifdef TCC_ARM_VFP |
op=0xED100A00; /* flds */ |
if(!sign) |
op|=0x800000; |
if ((ft & VT_BTYPE) != VT_FLOAT) |
op|=0x100; /* flds -> fldd */ |
o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); |
#else |
op=0xED100100; |
if(!sign) |
op|=0x800000; |
445,7 → 584,9 |
op|=0x400000; |
#endif |
o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); |
} else if((ft & VT_TYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_SHORT) { |
#endif |
} else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE |
|| (ft & VT_BTYPE) == VT_SHORT) { |
calcaddr(&base,&fc,&sign,255,0); |
op=0xE1500090; |
if ((ft & VT_BTYPE) == VT_SHORT) |
460,7 → 601,7 |
op=0xE5100000; |
if(!sign) |
op|=0x800000; |
if ((ft & VT_BTYPE) == VT_BYTE) |
if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) |
op|=0x400000; |
o(op|(intr(r)<<12)|fc|(base<<16)); |
} |
468,31 → 609,31 |
} |
} else { |
if (v == VT_CONST) { |
op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul); |
op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.i); |
if (fr & VT_SYM || !op) { |
o(0xE59F0000|(intr(r)<<12)); |
o(0xEA000000); |
if(fr & VT_SYM) |
greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); |
o(sv->c.ul); |
o(sv->c.i); |
} else |
o(op); |
return; |
} else if (v == VT_LOCAL) { |
op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul); |
op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.i); |
if (fr & VT_SYM || !op) { |
o(0xE59F0000|(intr(r)<<12)); |
o(0xEA000000); |
if(fr & VT_SYM) // needed ? |
greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); |
o(sv->c.ul); |
o(sv->c.i); |
o(0xE08B0000|(intr(r)<<12)|intr(r)); |
} else |
o(op); |
return; |
} else if(v == VT_CMP) { |
o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12)); |
o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12)); |
o(mapcc(sv->c.i)|0x3A00001|(intr(r)<<12)); |
o(mapcc(negcc(sv->c.i))|0x3A00000|(intr(r)<<12)); |
return; |
} else if (v == VT_JMP || v == VT_JMPI) { |
int t; |
499,18 → 640,22 |
t = v & 1; |
o(0xE3A00000|(intr(r)<<12)|t); |
o(0xEA000000); |
gsym(sv->c.ul); |
gsym(sv->c.i); |
o(0xE3A00000|(intr(r)<<12)|(t^1)); |
return; |
} else if (v < VT_CONST) { |
if(is_float(ft)) |
#ifdef TCC_ARM_VFP |
o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */ |
#else |
o(0xEE008180|(fpr(r)<<12)|fpr(v)); |
#endif |
else |
o(0xE1A00000|(intr(r)<<12)|intr(v)); |
return; |
} |
} |
error("load unimplemented!"); |
tcc_error("load unimplemented!"); |
} |
/* store register 'r' in lvalue 'v' */ |
518,11 → 663,11 |
{ |
SValue v1; |
int v, ft, fc, fr, sign; |
unsigned long op; |
uint32_t op; |
fr = sv->r; |
ft = sv->type.t; |
fc = sv->c.ul; |
fc = sv->c.i; |
if(fc>=0) |
sign=0; |
533,7 → 678,7 |
v = fr & VT_VALMASK; |
if (fr & VT_LVAL || fr == VT_LOCAL) { |
unsigned long base=0xb; |
uint32_t base = 0xb; |
if(v < VT_CONST) { |
base=intr(v); |
v=VT_LOCAL; |
541,7 → 686,7 |
} else if(v == VT_CONST) { |
v1.type.t = ft; |
v1.r = fr&~VT_LVAL; |
v1.c.ul = sv->c.ul; |
v1.c.i = sv->c.i; |
v1.sym=sv->sym; |
load(base=14, &v1); |
fc=sign=0; |
550,6 → 695,14 |
if(v == VT_LOCAL) { |
if(is_float(ft)) { |
calcaddr(&base,&fc,&sign,1020,2); |
#ifdef TCC_ARM_VFP |
op=0xED000A00; /* fsts */ |
if(!sign) |
op|=0x800000; |
if ((ft & VT_BTYPE) != VT_FLOAT) |
op|=0x100; /* fsts -> fstd */ |
o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); |
#else |
op=0xED000100; |
if(!sign) |
op|=0x800000; |
563,6 → 716,7 |
op|=0x400000; |
#endif |
o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); |
#endif |
return; |
} else if((ft & VT_BTYPE) == VT_SHORT) { |
calcaddr(&base,&fc,&sign,255,0); |
575,7 → 729,7 |
op=0xE5000000; |
if(!sign) |
op|=0x800000; |
if ((ft & VT_BTYPE) == VT_BYTE) |
if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) |
op|=0x400000; |
o(op|(intr(r)<<12)|fc|(base<<16)); |
} |
582,7 → 736,7 |
return; |
} |
} |
error("store unimplemented"); |
tcc_error("store unimplemented"); |
} |
static void gadd_sp(int val) |
595,9 → 749,9 |
{ |
int r; |
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
unsigned long x; |
uint32_t x; |
/* constant case */ |
x=encbranch(ind,ind+vtop->c.ul,0); |
x=encbranch(ind,ind+vtop->c.i,0); |
if(x) { |
if (vtop->r & VT_SYM) { |
/* relocation case */ |
611,7 → 765,7 |
o(0xE51FF004); // ldr pc,[pc,#-4] |
if (vtop->r & VT_SYM) |
greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); |
o(vtop->c.ul); |
o(vtop->c.i); |
} |
} else { |
/* otherwise, indirect call */ |
622,62 → 776,345 |
} |
} |
/* Generate function call. The function address is pushed first, then |
all the parameters in call order. This functions pops all the |
parameters and the function address. */ |
void gfunc_call(int nb_args) |
/* Return whether a structure is an homogeneous float aggregate or not. |
The answer is true if all the elements of the structure are of the same |
primitive float type and there is less than 4 elements. |
type: the type corresponding to the structure to be tested */ |
static int is_hgen_float_aggr(CType *type) |
{ |
int size, align, r, args_size, i; |
Sym *func_sym; |
signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}}; |
int todo=0xf, keep, plan2[4]={0,0,0,0}; |
if ((type->t & VT_BTYPE) == VT_STRUCT) { |
struct Sym *ref; |
int btype, nb_fields = 0; |
r = vtop->r & VT_VALMASK; |
if (r == VT_CMP || (r & ~1) == VT_JMP) |
gv(RC_INT); |
args_size = 0; |
for(i = nb_args ; i-- && args_size < 16 ;) { |
if ((vtop[-i].type.t & VT_BTYPE) == VT_STRUCT) { |
size = type_size(&vtop[-i].type, &align); |
ref = type->ref->next; |
btype = ref->type.t & VT_BTYPE; |
if (btype == VT_FLOAT || btype == VT_DOUBLE) { |
for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); |
return !ref && nb_fields <= 4; |
} |
} |
return 0; |
} |
struct avail_regs { |
signed char avail[3]; /* 3 holes max with only float and double alignments */ |
int first_hole; /* first available hole */ |
int last_hole; /* last available hole (none if equal to first_hole) */ |
int first_free_reg; /* next free register in the sequence, hole excluded */ |
}; |
#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 } |
/* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC |
param) according to the rules described in the procedure call standard for |
the ARM architecture (AAPCS). If found, the registers are assigned to this |
VFP CPRC parameter. Registers are allocated in sequence unless a hole exists |
and the parameter is a single float. |
avregs: opaque structure to keep track of available VFP co-processor regs |
align: alignment contraints for the param, as returned by type_size() |
size: size of the parameter, as returned by type_size() */ |
int assign_vfpreg(struct avail_regs *avregs, int align, int size) |
{ |
int first_reg = 0; |
if (avregs->first_free_reg == -1) |
return -1; |
if (align >> 3) { /* double alignment */ |
first_reg = avregs->first_free_reg; |
/* alignment contraint not respected so use next reg and record hole */ |
if (first_reg & 1) |
avregs->avail[avregs->last_hole++] = first_reg++; |
} else { /* no special alignment (float or array of float) */ |
/* if single float and a hole is available, assign the param to it */ |
if (size == 4 && avregs->first_hole != avregs->last_hole) |
return avregs->avail[avregs->first_hole++]; |
else |
first_reg = avregs->first_free_reg; |
} |
if (first_reg + size / 4 <= 16) { |
avregs->first_free_reg = first_reg + size / 4; |
return first_reg; |
} |
avregs->first_free_reg = -1; |
return -1; |
} |
/* Returns whether all params need to be passed in core registers or not. |
This is the case for function part of the runtime ABI. */ |
int floats_in_core_regs(SValue *sval) |
{ |
if (!sval->sym) |
return 0; |
switch (sval->sym->v) { |
case TOK___floatundisf: |
case TOK___floatundidf: |
case TOK___fixunssfdi: |
case TOK___fixunsdfdi: |
#ifndef TCC_ARM_VFP |
case TOK___fixunsxfdi: |
#endif |
case TOK___floatdisf: |
case TOK___floatdidf: |
case TOK___fixsfdi: |
case TOK___fixdfdi: |
return 1; |
default: |
return 0; |
} |
} |
/* Return the number of registers needed to return the struct, or 0 if |
returning via struct pointer. */ |
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) { |
#ifdef TCC_ARM_EABI |
int size, align; |
size = type_size(vt, &align); |
if (float_abi == ARM_HARD_FLOAT && !variadic && |
(is_float(vt->t) || is_hgen_float_aggr(vt))) { |
*ret_align = 8; |
*regsize = 8; |
ret->ref = NULL; |
ret->t = VT_DOUBLE; |
return (size + 7) >> 3; |
} else if (size <= 4) { |
*ret_align = 4; |
*regsize = 4; |
ret->ref = NULL; |
ret->t = VT_INT; |
return 1; |
} else |
return 0; |
#else |
return 0; |
#endif |
} |
/* Parameters are classified according to how they are copied to their final |
destination for the function call. Because the copying is performed class |
after class according to the order in the union below, it is important that |
some constraints about the order of the members of this union are respected: |
- CORE_STRUCT_CLASS must come after STACK_CLASS; |
- CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and |
VFP_STRUCT_CLASS; |
- VFP_STRUCT_CLASS must come after VFP_CLASS. |
See the comment for the main loop in copy_params() for the reason. */ |
enum reg_class { |
STACK_CLASS = 0, |
CORE_STRUCT_CLASS, |
VFP_CLASS, |
VFP_STRUCT_CLASS, |
CORE_CLASS, |
NB_CLASSES |
}; |
struct param_plan { |
int start; /* first reg or addr used depending on the class */ |
int end; /* last reg used or next free addr depending on the class */ |
SValue *sval; /* pointer to SValue on the value stack */ |
struct param_plan *prev; /* previous element in this class */ |
}; |
struct plan { |
struct param_plan *pplans; /* array of all the param plans */ |
struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */ |
}; |
#define add_param_plan(plan,pplan,class) \ |
do { \ |
pplan.prev = plan->clsplans[class]; \ |
plan->pplans[plan ## _nb] = pplan; \ |
plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \ |
} while(0) |
/* Assign parameters to registers and stack with alignment according to the |
rules in the procedure call standard for the ARM architecture (AAPCS). |
The overall assignment is recorded in an array of per parameter structures |
called parameter plans. The parameter plans are also further organized in a |
number of linked lists, one per class of parameter (see the comment for the |
definition of union reg_class). |
nb_args: number of parameters of the function for which a call is generated |
float_abi: float ABI in use for this function call |
plan: the structure where the overall assignment is recorded |
todo: a bitmap that record which core registers hold a parameter |
Returns the amount of stack space needed for parameter passing |
Note: this function allocated an array in plan->pplans with tcc_malloc. It |
is the responsibility of the caller to free this array once used (ie not |
before copy_params). */ |
static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) |
{ |
int i, size, align; |
int ncrn /* next core register number */, nsaa /* next stacked argument address*/; |
int plan_nb = 0; |
struct param_plan pplan; |
struct avail_regs avregs = AVAIL_REGS_INITIALIZER; |
ncrn = nsaa = 0; |
*todo = 0; |
plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans)); |
memset(plan->clsplans, 0, sizeof(plan->clsplans)); |
for(i = nb_args; i-- ;) { |
int j, start_vfpreg = 0; |
CType type = vtop[-i].type; |
type.t &= ~VT_ARRAY; |
size = type_size(&type, &align); |
size = (size + 3) & ~3; |
args_size += size; |
} else if ((vtop[-i].type.t & VT_BTYPE) == VT_FLOAT) |
args_size += 4; |
else if ((vtop[-i].type.t & VT_BTYPE) == VT_DOUBLE) |
args_size += 8; |
else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) |
args_size += LDOUBLE_SIZE; |
else { |
plan[nb_args-1-i][0]=args_size/4; |
args_size += 4; |
if ((vtop[-i].type.t & VT_BTYPE) == VT_LLONG && args_size < 16) { |
plan[nb_args-1-i][1]=args_size/4; |
args_size += 4; |
align = (align + 3) & ~3; |
switch(vtop[-i].type.t & VT_BTYPE) { |
case VT_STRUCT: |
case VT_FLOAT: |
case VT_DOUBLE: |
case VT_LDOUBLE: |
if (float_abi == ARM_HARD_FLOAT) { |
int is_hfa = 0; /* Homogeneous float aggregate */ |
if (is_float(vtop[-i].type.t) |
|| (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { |
int end_vfpreg; |
start_vfpreg = assign_vfpreg(&avregs, align, size); |
end_vfpreg = start_vfpreg + ((size - 1) >> 2); |
if (start_vfpreg >= 0) { |
pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]}; |
if (is_hfa) |
add_param_plan(plan, pplan, VFP_STRUCT_CLASS); |
else |
add_param_plan(plan, pplan, VFP_CLASS); |
continue; |
} else |
break; |
} |
} |
ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1); |
if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) { |
/* The parameter is allocated both in core register and on stack. As |
* such, it can be of either class: it would either be the last of |
* CORE_STRUCT_CLASS or the first of STACK_CLASS. */ |
for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) |
*todo|=(1<<j); |
pplan = (struct param_plan) {ncrn, j, &vtop[-i]}; |
add_param_plan(plan, pplan, CORE_STRUCT_CLASS); |
ncrn += size/4; |
if (ncrn > 4) |
nsaa = (ncrn - 4) * 4; |
} else { |
ncrn = 4; |
break; |
} |
args_size = keep = 0; |
for(i = 0;i < nb_args; i++) { |
vnrott(keep+1); |
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
size = type_size(&vtop->type, &align); |
continue; |
default: |
if (ncrn < 4) { |
int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; |
if (is_long) { |
ncrn = (ncrn + 1) & -2; |
if (ncrn == 4) |
break; |
} |
pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]}; |
ncrn++; |
if (is_long) |
pplan.end = ncrn++; |
add_param_plan(plan, pplan, CORE_CLASS); |
continue; |
} |
} |
nsaa = (nsaa + (align - 1)) & ~(align - 1); |
pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]}; |
add_param_plan(plan, pplan, STACK_CLASS); |
nsaa += size; /* size already rounded up before */ |
} |
return nsaa; |
} |
#undef add_param_plan |
/* Copy parameters to their final destination (core reg, VFP reg or stack) for |
function call. |
nb_args: number of parameters the function take |
plan: the overall assignment plan for parameters |
todo: a bitmap indicating what core reg will hold a parameter |
Returns the number of SValue added by this function on the value stack */ |
static int copy_params(int nb_args, struct plan *plan, int todo) |
{ |
int size, align, r, i, nb_extra_sval = 0; |
struct param_plan *pplan; |
/* Several constraints require parameters to be copied in a specific order: |
- structures are copied to the stack before being loaded in a reg; |
- floats loaded to an odd numbered VFP reg are first copied to the |
preceding even numbered VFP reg and then moved to the next VFP reg. |
It is thus important that: |
- structures assigned to core regs must be copied after parameters |
assigned to the stack but before structures assigned to VFP regs because |
a structure can lie partly in core registers and partly on the stack; |
- parameters assigned to the stack and all structures be copied before |
parameters assigned to a core reg since copying a parameter to the stack |
require using a core reg; |
- parameters assigned to VFP regs be copied before structures assigned to |
VFP regs as the copy might use an even numbered VFP reg that already |
holds part of a structure. */ |
for(i = 0; i < NB_CLASSES; i++) { |
for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) { |
vpushv(pplan->sval); |
pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ |
switch(i) { |
case STACK_CLASS: |
case CORE_STRUCT_CLASS: |
case VFP_STRUCT_CLASS: |
if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) { |
int padding = 0; |
size = type_size(&pplan->sval->type, &align); |
/* align to stack align size */ |
size = (size + 3) & ~3; |
if (i == STACK_CLASS && pplan->prev) |
padding = pplan->start - pplan->prev->end; |
size += padding; /* Add padding if any */ |
/* allocate the necessary size on stack */ |
gadd_sp(-size); |
/* generate structure store */ |
r = get_reg(RC_INT); |
o(0xE1A0000D|(intr(r)<<12)); |
o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */ |
vset(&vtop->type, r | VT_LVAL, 0); |
vswap(); |
vstore(); |
vtop--; |
args_size += size; |
} else if (is_float(vtop->type.t)) { |
vstore(); /* memcpy to current sp + potential padding */ |
/* Homogeneous float aggregate are loaded to VFP registers |
immediately since there is no way of loading data in multiple |
non consecutive VFP registers as what is done for other |
structures (see the use of todo). */ |
if (i == VFP_STRUCT_CLASS) { |
int first = pplan->start, nb = pplan->end - first + 1; |
/* vpop.32 {pplan->start, ..., pplan->end} */ |
o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb); |
/* No need to write the register used to a SValue since VFP regs |
cannot be used for gcall_or_jmp */ |
} |
} else { |
if (is_float(pplan->sval->type.t)) { |
#ifdef TCC_ARM_VFP |
r = vfpr(gv(RC_FLOAT)) << 12; |
if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) |
size = 4; |
else { |
size = 8; |
r |= 0x101; /* vpush.32 -> vpush.64 */ |
} |
o(0xED2D0A01 + r); /* vpush */ |
#else |
r=fpr(gv(RC_FLOAT))<<12; |
if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) |
if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) |
size = 4; |
else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) |
else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) |
size = 8; |
else |
size = LDOUBLE_SIZE; |
687,122 → 1124,238 |
else if(size == 8) |
r|=0x8000; |
o(0xED2D0100|r|(size>>2)); |
vtop--; |
args_size += size; |
o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */ |
#endif |
} else { |
int s; |
/* simple type (currently always same size) */ |
/* XXX: implicit cast ? */ |
size=4; |
if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { |
if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { |
lexpand_nr(); |
s=RC_INT; |
if(nb_args-i<5 && plan[nb_args-i-1][1]!=-1) { |
s=regmask(plan[nb_args-i-1][1]); |
todo&=~(1<<plan[nb_args-i-1][1]); |
} |
if(s==RC_INT) { |
r = gv(s); |
o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */ |
size = 8; |
r = gv(RC_INT); |
o(0xE52D0004|(intr(r)<<12)); /* push r */ |
vtop--; |
} else { |
plan2[keep]=s; |
keep++; |
vswap(); |
} |
size = 8; |
r = gv(RC_INT); |
o(0xE52D0004|(intr(r)<<12)); /* push r */ |
} |
s=RC_INT; |
if(nb_args-i<5 && plan[nb_args-i-1][0]!=-1) { |
s=regmask(plan[nb_args-i-1][0]); |
todo&=~(1<<plan[nb_args-i-1][0]); |
if (i == STACK_CLASS && pplan->prev) |
gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */ |
} |
if(s==RC_INT) { |
r = gv(s); |
o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */ |
break; |
case VFP_CLASS: |
gv(regmask(TREG_F0 + (pplan->start >> 1))); |
if (pplan->start & 1) { /* Must be in upper part of double register */ |
o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */ |
vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */ |
} |
break; |
case CORE_CLASS: |
if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { |
lexpand_nr(); |
gv(regmask(pplan->end)); |
pplan->sval->r2 = vtop->r; |
vtop--; |
} else { |
plan2[keep]=s; |
keep++; |
} |
args_size += size; |
gv(regmask(pplan->start)); |
/* Mark register as used so that gcall_or_jmp use another one |
(regs >=4 are free as never used to pass parameters) */ |
pplan->sval->r = vtop->r; |
break; |
} |
vtop--; |
} |
for(i=keep;i--;) { |
gv(plan2[i]); |
vrott(keep); |
} |
save_regs(keep); /* save used temporary registers */ |
keep++; |
if(args_size) { |
int n; |
n=args_size/4; |
if(n>4) |
n=4; |
todo&=((1<<n)-1); |
/* Manually free remaining registers since next parameters are loaded |
* manually, without the help of gv(int). */ |
save_regs(nb_args); |
if(todo) { |
int i; |
o(0xE8BD0000|todo); |
for(i=0;i<4;i++) |
if(todo&(1<<i)) { |
o(0xE8BD0000|todo); /* pop {todo} */ |
for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { |
int r; |
pplan->sval->r = pplan->start; |
/* An SValue can only pin 2 registers at best (r and r2) but a structure |
can occupy more than 2 registers. Thus, we need to push on the value |
stack some fake parameter to have on SValue for each registers used |
by a structure (r2 is not used). */ |
for (r = pplan->start + 1; r <= pplan->end; r++) { |
if (todo & (1 << r)) { |
nb_extra_sval++; |
vpushi(0); |
vtop->r=i; |
keep++; |
vtop->r = r; |
} |
} |
args_size-=n*4; |
} |
vnrott(keep); |
func_sym = vtop->type.ref; |
} |
return nb_extra_sval; |
} |
/* Generate function call. The function address is pushed first, then |
all the parameters in call order. This functions pops all the |
parameters and the function address. */ |
void gfunc_call(int nb_args) |
{ |
int r, args_size; |
int def_float_abi = float_abi; |
int todo; |
struct plan plan; |
#ifdef TCC_ARM_EABI |
int variadic; |
if (float_abi == ARM_HARD_FLOAT) { |
variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); |
if (variadic || floats_in_core_regs(&vtop[-nb_args])) |
float_abi = ARM_SOFTFP_FLOAT; |
} |
#endif |
/* cannot let cpu flags if other instruction are generated. Also avoid leaving |
VT_JMP anywhere except on the top of the stack because it would complicate |
the code generator. */ |
r = vtop->r & VT_VALMASK; |
if (r == VT_CMP || (r & ~1) == VT_JMP) |
gv(RC_INT); |
args_size = assign_regs(nb_args, float_abi, &plan, &todo); |
#ifdef TCC_ARM_EABI |
if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ |
args_size = (args_size + 7) & ~7; |
o(0xE24DD004); /* sub sp, sp, #4 */ |
} |
#endif |
nb_args += copy_params(nb_args, &plan, todo); |
tcc_free(plan.pplans); |
/* Move fct SValue on top as required by gcall_or_jmp */ |
vrotb(nb_args + 1); |
gcall_or_jmp(0); |
if (args_size) |
gadd_sp(args_size); |
vtop-=keep; |
gadd_sp(args_size); /* pop all parameters passed on the stack */ |
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { |
if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { |
o(0xEE000A10); /*vmov s0, r0 */ |
} else { |
o(0xEE000B10); /* vmov.32 d0[0], r0 */ |
o(0xEE201B10); /* vmov.32 d0[1], r1 */ |
} |
} |
#endif |
vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ |
leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ |
float_abi = def_float_abi; |
} |
/* generate function prolog of type 't' */ |
void gfunc_prolog(CType *func_type) |
{ |
Sym *sym,*sym2; |
int n,addr,size,align; |
int n, nf, size, align, rs, struct_ret = 0; |
int addr, pn, sn; /* pn=core, sn=stack */ |
CType ret_type; |
#ifdef TCC_ARM_EABI |
struct avail_regs avregs = AVAIL_REGS_INITIALIZER; |
#endif |
sym = func_type->ref; |
func_vt = sym->type; |
func_var = (func_type->ref->c == FUNC_ELLIPSIS); |
n=0; |
addr=12; |
if((func_vt.t & VT_BTYPE) == VT_STRUCT) { |
func_vc = addr; |
addr += 4; |
n = nf = 0; |
if ((func_vt.t & VT_BTYPE) == VT_STRUCT && |
!gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs)) |
{ |
n++; |
struct_ret = 1; |
func_vc = 12; /* Offset from fp of the place to store the result */ |
} |
for(sym2=sym->next;sym2 && n<4;sym2=sym2->next) { |
for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { |
size = type_size(&sym2->type, &align); |
size = (size + 3) & ~3; |
n+=size/4; |
#ifdef TCC_ARM_EABI |
if (float_abi == ARM_HARD_FLOAT && !func_var && |
(is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { |
int tmpnf = assign_vfpreg(&avregs, align, size); |
tmpnf += (size + 3) / 4; |
nf = (tmpnf > nf) ? tmpnf : nf; |
} else |
#endif |
if (n < 4) |
n += (size + 3) / 4; |
} |
o(0xE1A0C00D); /* mov ip,sp */ |
if(func_type->ref->c == FUNC_ELLIPSIS) |
if (func_var) |
n=4; |
if(n) { |
if(n>4) |
n=4; |
#ifdef TCC_ARM_EABI |
n=(n+1)&-2; |
#endif |
o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */ |
} |
if (nf) { |
if (nf>16) |
nf=16; |
nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */ |
o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */ |
} |
o(0xE92D5800); /* save fp, ip, lr*/ |
o(0xE1A0B00D); /* mov fp,sp */ |
func_sub_sp_offset = ind; |
o(0xE1A00000); /* nop, leave space for stack adjustment */ |
o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ |
#ifdef TCC_ARM_EABI |
if (float_abi == ARM_HARD_FLOAT) { |
func_vc += nf * 4; |
avregs = AVAIL_REGS_INITIALIZER; |
} |
#endif |
pn = struct_ret, sn = 0; |
while ((sym = sym->next)) { |
CType *type; |
type = &sym->type; |
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr); |
size = type_size(type, &align); |
size = (size + 3) & ~3; |
addr += size; |
size = (size + 3) >> 2; |
align = (align + 3) & ~3; |
#ifdef TCC_ARM_EABI |
if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) |
|| is_hgen_float_aggr(&sym->type))) { |
int fpn = assign_vfpreg(&avregs, align, size << 2); |
if (fpn >= 0) |
addr = fpn * 4; |
else |
goto from_stack; |
} else |
#endif |
if (pn < 4) { |
#ifdef TCC_ARM_EABI |
pn = (pn + (align-1)/4) & -(align/4); |
#endif |
addr = (nf + pn) * 4; |
pn += size; |
if (!sn && pn > 4) |
sn = (pn - 4); |
} else { |
#ifdef TCC_ARM_EABI |
from_stack: |
sn = (sn + (align-1)/4) & -(align/4); |
#endif |
addr = (n + nf + sn) * 4; |
sn += size; |
} |
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), |
addr + 12); |
} |
last_itod_magic=0; |
leaffunc = 1; |
loc = 0; |
} |
809,20 → 1362,38 |
/* generate function epilog */ |
void gfunc_epilog(void) |
{ |
unsigned long x; |
uint32_t x; |
int diff; |
/* Copy float return value to core register if base standard is used and |
float computation is made with VFP */ |
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { |
if((func_vt.t & VT_BTYPE) == VT_FLOAT) |
o(0xEE100A10); /* fmrs r0, s0 */ |
else { |
o(0xEE100B10); /* fmrdl r0, d0 */ |
o(0xEE301B10); /* fmrdh r1, d0 */ |
} |
} |
#endif |
o(0xE89BA800); /* restore fp, sp, pc */ |
if(loc) { |
x=stuff_const(0xE24DD000, (-loc + 3) & -4); /* sub sp,sp,# */ |
diff = (-loc + 3) & -4; |
#ifdef TCC_ARM_EABI |
if(!leaffunc) |
diff = ((diff + 11) & -8) - 4; |
#endif |
if(diff > 0) { |
x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */ |
if(x) |
*(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = x; |
*(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x; |
else { |
unsigned long addr; |
int addr; |
addr=ind; |
o(0xE59FC004); /* ldr ip,[pc+4] */ |
o(0xE04DD00C); /* sub sp,sp,ip */ |
o(0xE04BD00C); /* sub sp,fp,ip */ |
o(0xE1A0F00E); /* mov pc,lr */ |
o((-loc + 3) & -4); |
*(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1); |
o(diff); |
*(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1); |
} |
} |
} |
846,7 → 1417,7 |
int gtst(int inv, int t) |
{ |
int v, r; |
unsigned long op; |
uint32_t op; |
v = vtop->r & VT_VALMASK; |
r=ind; |
if (v == VT_CMP) { |
859,7 → 1430,7 |
if(!vtop->c.i) |
vtop->c.i=t; |
else { |
unsigned long *x; |
uint32_t *x; |
int p,lp; |
if(t) { |
p = vtop->c.i; |
866,7 → 1437,7 |
do { |
p = decbranch(lp=p); |
} while(p); |
x = (unsigned long *)(cur_text_section->data + lp); |
x = (uint32_t *)(cur_text_section->data + lp); |
*x &= 0xff000000; |
*x |= encbranch(lp,t,1); |
} |
876,25 → 1447,7 |
t = gjmp(t); |
gsym(vtop->c.i); |
} |
} else { |
if (is_float(vtop->type.t)) { |
r=gv(RC_FLOAT); |
o(0xEE90F118|fpr(r)<<16); |
vtop->r = VT_CMP; |
vtop->c.i = TOK_NE; |
return gtst(inv, t); |
} else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
/* constant jmp optimization */ |
if ((vtop->c.i != 0) != inv) |
t = gjmp(t); |
} else { |
v = gv(RC_INT); |
o(0xE3300000|(intr(v)<<16)); |
vtop->r = VT_CMP; |
vtop->c.i = TOK_NE; |
return gtst(inv, t); |
} |
} |
vtop--; |
return t; |
} |
903,7 → 1456,8 |
void gen_opi(int op) |
{ |
int c, func = 0; |
unsigned long opc = 0,r,fr; |
uint32_t opc = 0, r, fr; |
unsigned short retreg = REG_IRET; |
c=0; |
switch(op) { |
972,11 → 1526,21 |
c=3; |
break; |
case '%': |
#ifdef TCC_ARM_EABI |
func=TOK___aeabi_idivmod; |
retreg=REG_LRET; |
#else |
func=TOK___modsi3; |
#endif |
c=3; |
break; |
case TOK_UMOD: |
#ifdef TCC_ARM_EABI |
func=TOK___aeabi_uidivmod; |
retreg=REG_LRET; |
#else |
func=TOK___umodsi3; |
#endif |
c=3; |
break; |
case TOK_UMULL: |
1008,7 → 1572,7 |
vswap(); |
opc=0xE0000000|(opc<<20)|(c<<16); |
if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
unsigned long x; |
uint32_t x; |
x=stuff_const(opc|0x2000000,vtop->c.i); |
if(x) { |
r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); |
1051,17 → 1615,121 |
vrott(3); |
gfunc_call(2); |
vpushi(0); |
vtop->r = REG_IRET; |
vtop->r = retreg; |
break; |
default: |
error("gen_opi %i unimplemented!",op); |
tcc_error("gen_opi %i unimplemented!",op); |
} |
} |
static int is_fconst() |
#ifdef TCC_ARM_VFP |
static int is_zero(int i) |
{ |
if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
return 0; |
if (vtop[i].type.t == VT_FLOAT) |
return (vtop[i].c.f == 0.f); |
else if (vtop[i].type.t == VT_DOUBLE) |
return (vtop[i].c.d == 0.0); |
return (vtop[i].c.ld == 0.l); |
} |
/* generate a floating point operation 'v = t1 op t2' instruction. The |
* two operands are guaranted to have the same floating point type */ |
void gen_opf(int op) |
{ |
uint32_t x; |
int fneg=0,r; |
x=0xEE000A00|T2CPR(vtop->type.t); |
switch(op) { |
case '+': |
if(is_zero(-1)) |
vswap(); |
if(is_zero(0)) { |
vtop--; |
return; |
} |
x|=0x300000; |
break; |
case '-': |
x|=0x300040; |
if(is_zero(0)) { |
vtop--; |
return; |
} |
if(is_zero(-1)) { |
x|=0x810000; /* fsubX -> fnegX */ |
vswap(); |
vtop--; |
fneg=1; |
} |
break; |
case '*': |
x|=0x200000; |
break; |
case '/': |
x|=0x800000; |
break; |
default: |
if(op < TOK_ULT || op > TOK_GT) { |
tcc_error("unknown fp op %x!",op); |
return; |
} |
if(is_zero(-1)) { |
vswap(); |
switch(op) { |
case TOK_LT: op=TOK_GT; break; |
case TOK_GE: op=TOK_ULE; break; |
case TOK_LE: op=TOK_GE; break; |
case TOK_GT: op=TOK_ULT; break; |
} |
} |
x|=0xB40040; /* fcmpX */ |
if(op!=TOK_EQ && op!=TOK_NE) |
x|=0x80; /* fcmpX -> fcmpeX */ |
if(is_zero(0)) { |
vtop--; |
o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */ |
} else { |
x|=vfpr(gv(RC_FLOAT)); |
vswap(); |
o(x|(vfpr(gv(RC_FLOAT))<<12)); |
vtop--; |
} |
o(0xEEF1FA10); /* fmstat */ |
switch(op) { |
case TOK_LE: op=TOK_ULE; break; |
case TOK_LT: op=TOK_ULT; break; |
case TOK_UGE: op=TOK_GE; break; |
case TOK_UGT: op=TOK_GT; break; |
} |
vtop->r = VT_CMP; |
vtop->c.i = op; |
return; |
} |
r=gv(RC_FLOAT); |
x|=vfpr(r); |
r=regmask(r); |
if(!fneg) { |
int r2; |
vswap(); |
r2=gv(RC_FLOAT); |
x|=vfpr(r2)<<16; |
r|=regmask(r2); |
} |
vtop->r=get_reg_ex(RC_FLOAT,r); |
if(!fneg) |
vtop--; |
o(x|(vfpr(vtop->r)<<12)); |
} |
#else |
static uint32_t is_fconst() |
{ |
long double f; |
int r; |
uint32_t r; |
if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
return 0; |
if (vtop->type.t == VT_FLOAT) |
1100,8 → 1768,7 |
two operands are guaranted to have the same floating point type */ |
void gen_opf(int op) |
{ |
unsigned long x; |
int r,r2,c1,c2; |
uint32_t x, r, r2, c1, c2; |
//fputs("gen_opf\n",stderr); |
vswap(); |
c1 = is_fconst(); |
1193,25 → 1860,21 |
default: |
if(op >= TOK_ULT && op <= TOK_GT) { |
x|=0xd0f110; // cmfe |
/* bug (intention?) in Linux FPU emulator |
doesn't set carry if equal */ |
switch(op) { |
case TOK_ULT: |
case TOK_UGE: |
case TOK_ULE: |
case TOK_UGT: |
fputs("unsigned comparision on floats?\n",stderr); |
tcc_error("unsigned comparison on floats?"); |
break; |
case TOK_LT: |
op=TOK_ULT; |
op=TOK_Nset; |
break; |
case TOK_GE: |
op=TOK_UGE; |
break; |
case TOK_LE: |
op=TOK_ULE; |
op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */ |
break; |
case TOK_GT: |
op=TOK_UGT; |
break; |
case TOK_EQ: |
case TOK_NE: |
x&=~0x400000; // cmfe -> cmf |
1221,26 → 1884,20 |
c2=c1; |
vswap(); |
switch(op) { |
case TOK_ULT: |
op=TOK_UGT; |
case TOK_Nset: |
op=TOK_GT; |
break; |
case TOK_UGE: |
case TOK_GE: |
op=TOK_ULE; |
break; |
case TOK_ULE: |
op=TOK_UGE; |
op=TOK_GE; |
break; |
case TOK_UGT: |
op=TOK_ULT; |
case TOK_GT: |
op=TOK_Nset; |
break; |
} |
} |
// bug (intention?) in Linux FPU emulator |
// doesn't set carry if equal |
if(op==TOK_ULT) |
op=TOK_LT; |
else if(op==TOK_UGE) |
op=TOK_GE; |
vswap(); |
r=fpr(gv(RC_FLOAT)); |
vswap(); |
1254,7 → 1911,7 |
vtop[-1].r = VT_CMP; |
vtop[-1].c.i = op; |
} else { |
error("unknown fp op %x!\n",op); |
tcc_error("unknown fp op %x!",op); |
return; |
} |
} |
1270,20 → 1927,35 |
vtop--; |
o(x|(r<<16)|(c1<<12)|r2); |
} |
#endif |
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int' |
and 'long long' cases. */ |
void gen_cvt_itof(int t) |
ST_FUNC void gen_cvt_itof1(int t) |
{ |
int r,r2,bt; |
uint32_t r, r2; |
int bt; |
bt=vtop->type.t & VT_BTYPE; |
if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) { |
#ifndef TCC_ARM_VFP |
uint32_t dsize = 0; |
#endif |
r=intr(gv(RC_INT)); |
#ifdef TCC_ARM_VFP |
r2=vfpr(vtop->r=get_reg(RC_FLOAT)); |
o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */ |
r2|=r2<<12; |
if(!(vtop->type.t & VT_UNSIGNED)) |
r2|=0x80; /* fuitoX -> fsituX */ |
o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/ |
#else |
r2=fpr(vtop->r=get_reg(RC_FLOAT)); |
o(0xEE000190|(r2<<16)|(r<<12)); |
if((t & VT_BTYPE) != VT_FLOAT) |
dsize=0x80; /* flts -> fltd */ |
o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */ |
if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) { |
unsigned int off=0; |
o(0xE3500000|(r<<12)); |
uint32_t off = 0; |
o(0xE3500000|(r<<12)); /* cmp */ |
r=fpr(get_reg(RC_FLOAT)); |
if(last_itod_magic) { |
off=ind+8-last_itod_magic; |
1291,23 → 1963,44 |
if(off>255) |
off=0; |
} |
o(0xBD1F8100|(r<<12)|off); |
o(0xBD1F0100|(r<<12)|off); /* ldflts */ |
if(!off) { |
o(0xEA000001); |
o(0xEA000000); /* b */ |
last_itod_magic=ind; |
o(0x41F00000); |
o(0); |
o(0x4F800000); /* 4294967296.0f */ |
} |
o(0xBE000180|(r2<<16)|(r2<<12)|r); |
o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */ |
} |
#endif |
return; |
} else if(bt == VT_LLONG) { |
int func; |
CType *func_type = 0; |
if((t & VT_BTYPE) == VT_FLOAT) { |
func_type = &func_float_type; |
if(vtop->type.t & VT_UNSIGNED) |
func=TOK___ulltold; |
func=TOK___floatundisf; |
else |
func=TOK___slltold; |
vpush_global_sym(&func_old_type, func); |
func=TOK___floatdisf; |
#if LDOUBLE_SIZE != 8 |
} else if((t & VT_BTYPE) == VT_LDOUBLE) { |
func_type = &func_ldouble_type; |
if(vtop->type.t & VT_UNSIGNED) |
func=TOK___floatundixf; |
else |
func=TOK___floatdixf; |
} else if((t & VT_BTYPE) == VT_DOUBLE) { |
#else |
} else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) { |
#endif |
func_type = &func_double_type; |
if(vtop->type.t & VT_UNSIGNED) |
func=TOK___floatundidf; |
else |
func=TOK___floatdidf; |
} |
if(func_type) { |
vpush_global_sym(func_type, func); |
vswap(); |
gfunc_call(1); |
vpushi(0); |
1314,28 → 2007,38 |
vtop->r=TREG_F0; |
return; |
} |
error("unimplemented gen_cvt_itof %x!",vtop->type.t); |
} |
tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t); |
} |
/* convert fp to int 't' type */ |
void gen_cvt_ftoi(int t) |
{ |
int r,r2,u,func=0; |
uint32_t r, r2; |
int u, func = 0; |
u=t&VT_UNSIGNED; |
t&=VT_BTYPE; |
r2=vtop->type.t & VT_BTYPE; |
if(t==VT_INT) { |
#ifdef TCC_ARM_VFP |
r=vfpr(gv(RC_FLOAT)); |
u=u?0:0x10000; |
o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */ |
r2=intr(vtop->r=get_reg(RC_INT)); |
o(0xEE100A10|(r<<16)|(r2<<12)); |
return; |
#else |
if(u) { |
if(r2 == VT_FLOAT) |
func=TOK___fixunssfsi; |
#if LDOUBLE_SIZE != 8 |
else if(r2 == VT_LDOUBLE) |
func=TOK___fixunsxfsi; |
else if(r2 == VT_DOUBLE) |
func=TOK___fixunsdfsi; |
else if(r2 == VT_LDOUBLE) |
#if LDOUBLE_SIZE == 8 |
func=TOK___fixunsdfsi; |
#else |
func=TOK___fixunsxfsi; |
else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) |
#endif |
func=TOK___fixunsdfsi; |
} else { |
r=fpr(gv(RC_FLOAT)); |
r2=intr(vtop->r=get_reg(RC_INT)); |
1342,17 → 2045,18 |
o(0xEE100170|(r2<<12)|r); |
return; |
} |
#endif |
} else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1 |
if(r2 == VT_FLOAT) |
func=TOK___fixsfdi; |
#if LDOUBLE_SIZE != 8 |
else if(r2 == VT_LDOUBLE) |
func=TOK___fixxfdi; |
else if(r2 == VT_DOUBLE) |
func=TOK___fixdfdi; |
else if(r2 == VT_LDOUBLE) |
#if LDOUBLE_SIZE == 8 |
func=TOK___fixdfdi; |
#else |
func=TOK___fixxfdi; |
else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) |
#endif |
func=TOK___fixdfdi; |
} |
if(func) { |
vpush_global_sym(&func_old_type, func); |
1364,14 → 2068,21 |
vtop->r = REG_IRET; |
return; |
} |
error("unimplemented gen_cvt_ftoi!"); |
tcc_error("unimplemented gen_cvt_ftoi!"); |
} |
/* convert from one floating point type to another */ |
void gen_cvt_ftof(int t) |
{ |
/* all we have to do on i386 and ARM is to put the float in a register */ |
#ifdef TCC_ARM_VFP |
if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) { |
uint32_t r = vfpr(gv(RC_FLOAT)); |
o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t)); |
} |
#else |
/* all we have to do on i386 and FPA ARM is to put the float in a register */ |
gv(RC_FLOAT); |
#endif |
} |
/* computed goto support */ |
1381,6 → 2092,22 |
vtop--; |
} |
/* Save the stack pointer onto the stack and return the location of its address */ |
ST_FUNC void gen_vla_sp_save(int addr) { |
tcc_error("variable length arrays unsupported for this target"); |
} |
/* Restore the SP from a location on the stack */ |
ST_FUNC void gen_vla_sp_restore(int addr) { |
tcc_error("variable length arrays unsupported for this target"); |
} |
/* Subtract from the stack pointer, and push the resulting value onto the stack */ |
ST_FUNC void gen_vla_alloc(CType *type, int align) { |
tcc_error("variable length arrays unsupported for this target"); |
} |
/* end of ARM code generator */ |
/*************************************************************/ |
#endif |
/*************************************************************/ |
/programs/develop/ktcc/trunk/source/arm64-gen.c |
---|
0,0 → 1,1845 |
/* |
* A64 code generator for TCC |
* |
* Copyright (c) 2014-2015 Edmund Grimley Evans |
* |
* Copying and distribution of this file, with or without modification, |
* are permitted in any medium without royalty provided the copyright |
* notice and this notice are preserved. This file is offered as-is, |
* without any warranty. |
*/ |
#ifdef TARGET_DEFS_ONLY |
// Number of registers available to allocator: |
#define NB_REGS 28 // x0-x18, x30, v0-v7 |
#define TREG_R(x) (x) // x = 0..18 |
#define TREG_R30 19 |
#define TREG_F(x) (x + 20) // x = 0..7 |
// Register classes sorted from more general to more precise: |
#define RC_INT (1 << 0) |
#define RC_FLOAT (1 << 1) |
#define RC_R(x) (1 << (2 + (x))) // x = 0..18 |
#define RC_R30 (1 << 21) |
#define RC_F(x) (1 << (22 + (x))) // x = 0..7 |
#define RC_IRET (RC_R(0)) // int return register class |
#define RC_FRET (RC_F(0)) // float return register class |
#define REG_IRET (TREG_R(0)) // int return register number |
#define REG_FRET (TREG_F(0)) // float return register number |
#define PTR_SIZE 8 |
#define LDOUBLE_SIZE 16 |
#define LDOUBLE_ALIGN 16 |
#define MAX_ALIGN 16 |
#define CHAR_IS_UNSIGNED |
/******************************************************/ |
/* ELF defines */ |
#define EM_TCC_TARGET EM_AARCH64 |
#define R_DATA_32 R_AARCH64_ABS32 |
#define R_DATA_PTR R_AARCH64_ABS64 |
#define R_JMP_SLOT R_AARCH64_JUMP_SLOT |
#define R_COPY R_AARCH64_COPY |
#define ELF_START_ADDR 0x00400000 |
#define ELF_PAGE_SIZE 0x1000 |
/******************************************************/ |
#else /* ! TARGET_DEFS_ONLY */ |
/******************************************************/ |
#include "tcc.h" |
#include <assert.h> |
ST_DATA const int reg_classes[NB_REGS] = { |
RC_INT | RC_R(0), |
RC_INT | RC_R(1), |
RC_INT | RC_R(2), |
RC_INT | RC_R(3), |
RC_INT | RC_R(4), |
RC_INT | RC_R(5), |
RC_INT | RC_R(6), |
RC_INT | RC_R(7), |
RC_INT | RC_R(8), |
RC_INT | RC_R(9), |
RC_INT | RC_R(10), |
RC_INT | RC_R(11), |
RC_INT | RC_R(12), |
RC_INT | RC_R(13), |
RC_INT | RC_R(14), |
RC_INT | RC_R(15), |
RC_INT | RC_R(16), |
RC_INT | RC_R(17), |
RC_INT | RC_R(18), |
RC_R30, // not in RC_INT as we make special use of x30 |
RC_FLOAT | RC_F(0), |
RC_FLOAT | RC_F(1), |
RC_FLOAT | RC_F(2), |
RC_FLOAT | RC_F(3), |
RC_FLOAT | RC_F(4), |
RC_FLOAT | RC_F(5), |
RC_FLOAT | RC_F(6), |
RC_FLOAT | RC_F(7) |
}; |
#define IS_FREG(x) ((x) >= TREG_F(0)) |
static uint32_t intr(int r) |
{ |
assert(TREG_R(0) <= r && r <= TREG_R30); |
return r < TREG_R30 ? r : 30; |
} |
static uint32_t fltr(int r) |
{ |
assert(TREG_F(0) <= r && r <= TREG_F(7)); |
return r - TREG_F(0); |
} |
// Add an instruction to text section: |
ST_FUNC void o(unsigned int c) |
{ |
int ind1 = ind + 4; |
if (ind1 > cur_text_section->data_allocated) |
section_realloc(cur_text_section, ind1); |
write32le(cur_text_section->data + ind, c); |
ind = ind1; |
} |
static int arm64_encode_bimm64(uint64_t x) |
{ |
int neg = x & 1; |
int rep, pos, len; |
if (neg) |
x = ~x; |
if (!x) |
return -1; |
if (x >> 2 == (x & (((uint64_t)1 << (64 - 2)) - 1))) |
rep = 2, x &= ((uint64_t)1 << 2) - 1; |
else if (x >> 4 == (x & (((uint64_t)1 << (64 - 4)) - 1))) |
rep = 4, x &= ((uint64_t)1 << 4) - 1; |
else if (x >> 8 == (x & (((uint64_t)1 << (64 - 8)) - 1))) |
rep = 8, x &= ((uint64_t)1 << 8) - 1; |
else if (x >> 16 == (x & (((uint64_t)1 << (64 - 16)) - 1))) |
rep = 16, x &= ((uint64_t)1 << 16) - 1; |
else if (x >> 32 == (x & (((uint64_t)1 << (64 - 32)) - 1))) |
rep = 32, x &= ((uint64_t)1 << 32) - 1; |
else |
rep = 64; |
pos = 0; |
if (!(x & (((uint64_t)1 << 32) - 1))) x >>= 32, pos += 32; |
if (!(x & (((uint64_t)1 << 16) - 1))) x >>= 16, pos += 16; |
if (!(x & (((uint64_t)1 << 8) - 1))) x >>= 8, pos += 8; |
if (!(x & (((uint64_t)1 << 4) - 1))) x >>= 4, pos += 4; |
if (!(x & (((uint64_t)1 << 2) - 1))) x >>= 2, pos += 2; |
if (!(x & (((uint64_t)1 << 1) - 1))) x >>= 1, pos += 1; |
len = 0; |
if (!(~x & (((uint64_t)1 << 32) - 1))) x >>= 32, len += 32; |
if (!(~x & (((uint64_t)1 << 16) - 1))) x >>= 16, len += 16; |
if (!(~x & (((uint64_t)1 << 8) - 1))) x >>= 8, len += 8; |
if (!(~x & (((uint64_t)1 << 4) - 1))) x >>= 4, len += 4; |
if (!(~x & (((uint64_t)1 << 2) - 1))) x >>= 2, len += 2; |
if (!(~x & (((uint64_t)1 << 1) - 1))) x >>= 1, len += 1; |
if (x) |
return -1; |
if (neg) { |
pos = (pos + len) & (rep - 1); |
len = rep - len; |
} |
return ((0x1000 & rep << 6) | (((rep - 1) ^ 31) << 1 & 63) | |
((rep - pos) & (rep - 1)) << 6 | (len - 1)); |
} |
static uint32_t arm64_movi(int r, uint64_t x) |
{ |
uint64_t m = 0xffff; |
int e; |
if (!(x & ~m)) |
return 0x52800000 | r | x << 5; // movz w(r),#(x) |
if (!(x & ~(m << 16))) |
return 0x52a00000 | r | x >> 11; // movz w(r),#(x >> 16),lsl #16 |
if (!(x & ~(m << 32))) |
return 0xd2c00000 | r | x >> 27; // movz x(r),#(x >> 32),lsl #32 |
if (!(x & ~(m << 48))) |
return 0xd2e00000 | r | x >> 43; // movz x(r),#(x >> 48),lsl #48 |
if ((x & ~m) == m << 16) |
return (0x12800000 | r | |
(~x << 5 & 0x1fffe0)); // movn w(r),#(~x) |
if ((x & ~(m << 16)) == m) |
return (0x12a00000 | r | |
(~x >> 11 & 0x1fffe0)); // movn w(r),#(~x >> 16),lsl #16 |
if (!~(x | m)) |
return (0x92800000 | r | |
(~x << 5 & 0x1fffe0)); // movn x(r),#(~x) |
if (!~(x | m << 16)) |
return (0x92a00000 | r | |
(~x >> 11 & 0x1fffe0)); // movn x(r),#(~x >> 16),lsl #16 |
if (!~(x | m << 32)) |
return (0x92c00000 | r | |
(~x >> 27 & 0x1fffe0)); // movn x(r),#(~x >> 32),lsl #32 |
if (!~(x | m << 48)) |
return (0x92e00000 | r | |
(~x >> 43 & 0x1fffe0)); // movn x(r),#(~x >> 32),lsl #32 |
if (!(x >> 32) && (e = arm64_encode_bimm64(x | x << 32)) >= 0) |
return 0x320003e0 | r | (uint32_t)e << 10; // movi w(r),#(x) |
if ((e = arm64_encode_bimm64(x)) >= 0) |
return 0xb20003e0 | r | (uint32_t)e << 10; // movi x(r),#(x) |
return 0; |
} |
static void arm64_movimm(int r, uint64_t x) |
{ |
uint32_t i; |
if ((i = arm64_movi(r, x))) |
o(i); // a single MOV |
else { |
// MOVZ/MOVN and 1-3 MOVKs |
int z = 0, m = 0; |
uint32_t mov1 = 0xd2800000; // movz |
uint64_t x1 = x; |
for (i = 0; i < 64; i += 16) { |
z += !(x >> i & 0xffff); |
m += !(~x >> i & 0xffff); |
} |
if (m > z) { |
x1 = ~x; |
mov1 = 0x92800000; // movn |
} |
for (i = 0; i < 64; i += 16) |
if (x1 >> i & 0xffff) { |
o(mov1 | r | (x1 >> i & 0xffff) << 5 | i << 17); |
// movz/movn x(r),#(*),lsl #(i) |
break; |
} |
for (i += 16; i < 64; i += 16) |
if (x1 >> i & 0xffff) |
o(0xf2800000 | r | (x >> i & 0xffff) << 5 | i << 17); |
// movk x(r),#(*),lsl #(i) |
} |
} |
// Patch all branches in list pointed to by t to branch to a: |
ST_FUNC void gsym_addr(int t_, int a_) |
{ |
uint32_t t = t_; |
uint32_t a = a_; |
while (t) { |
unsigned char *ptr = cur_text_section->data + t; |
uint32_t next = read32le(ptr); |
if (a - t + 0x8000000 >= 0x10000000) |
tcc_error("branch out of range"); |
write32le(ptr, (a - t == 4 ? 0xd503201f : // nop |
0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b |
t = next; |
} |
} |
// Patch all branches in list pointed to by t to branch to current location: |
ST_FUNC void gsym(int t) |
{ |
gsym_addr(t, ind); |
} |
static int arm64_type_size(int t) |
{ |
switch (t & VT_BTYPE) { |
case VT_INT: return 2; |
case VT_BYTE: return 0; |
case VT_SHORT: return 1; |
case VT_PTR: return 3; |
case VT_ENUM: return 2; |
case VT_FUNC: return 3; |
case VT_FLOAT: return 2; |
case VT_DOUBLE: return 3; |
case VT_LDOUBLE: return 4; |
case VT_BOOL: return 0; |
case VT_LLONG: return 3; |
} |
assert(0); |
return 0; |
} |
static void arm64_spoff(int reg, uint64_t off) |
{ |
uint32_t sub = off >> 63; |
if (sub) |
off = -off; |
if (off < 4096) |
o(0x910003e0 | sub << 30 | reg | off << 10); |
// (add|sub) x(reg),sp,#(off) |
else { |
arm64_movimm(30, off); // use x30 for offset |
o(0x8b3e63e0 | sub << 30 | reg); // (add|sub) x(reg),sp,x30 |
} |
} |
static void arm64_ldrx(int sg, int sz_, int dst, int bas, uint64_t off) |
{ |
uint32_t sz = sz_; |
if (sz >= 2) |
sg = 0; |
if (!(off & ~((uint32_t)0xfff << sz))) |
o(0x39400000 | dst | bas << 5 | off << (10 - sz) | |
(uint32_t)!!sg << 23 | sz << 30); // ldr(*) x(dst),[x(bas),#(off)] |
else if (off < 256 || -off <= 256) |
o(0x38400000 | dst | bas << 5 | (off & 511) << 12 | |
(uint32_t)!!sg << 23 | sz << 30); // ldur(*) x(dst),[x(bas),#(off)] |
else { |
arm64_movimm(30, off); // use x30 for offset |
o(0x38206800 | dst | bas << 5 | (uint32_t)30 << 16 | |
(uint32_t)(!!sg + 1) << 22 | sz << 30); // ldr(*) x(dst),[x(bas),x30] |
} |
} |
static void arm64_ldrv(int sz_, int dst, int bas, uint64_t off) |
{ |
uint32_t sz = sz_; |
if (!(off & ~((uint32_t)0xfff << sz))) |
o(0x3d400000 | dst | bas << 5 | off << (10 - sz) | |
(sz & 4) << 21 | (sz & 3) << 30); // ldr (s|d|q)(dst),[x(bas),#(off)] |
else if (off < 256 || -off <= 256) |
o(0x3c400000 | dst | bas << 5 | (off & 511) << 12 | |
(sz & 4) << 21 | (sz & 3) << 30); // ldur (s|d|q)(dst),[x(bas),#(off)] |
else { |
arm64_movimm(30, off); // use x30 for offset |
o(0x3c606800 | dst | bas << 5 | (uint32_t)30 << 16 | |
sz << 30 | (sz & 4) << 21); // ldr (s|d|q)(dst),[x(bas),x30] |
} |
} |
static void arm64_ldrs(int reg_, int size) |
{ |
uint32_t reg = reg_; |
// Use x30 for intermediate value in some cases. |
switch (size) { |
default: assert(0); break; |
case 1: |
arm64_ldrx(0, 0, reg, reg, 0); |
break; |
case 2: |
arm64_ldrx(0, 1, reg, reg, 0); |
break; |
case 3: |
arm64_ldrx(0, 1, 30, reg, 0); |
arm64_ldrx(0, 0, reg, reg, 2); |
o(0x2a0043c0 | reg | reg << 16); // orr x(reg),x30,x(reg),lsl #16 |
break; |
case 4: |
arm64_ldrx(0, 2, reg, reg, 0); |
break; |
case 5: |
arm64_ldrx(0, 2, 30, reg, 0); |
arm64_ldrx(0, 0, reg, reg, 4); |
o(0xaa0083c0 | reg | reg << 16); // orr x(reg),x30,x(reg),lsl #32 |
break; |
case 6: |
arm64_ldrx(0, 2, 30, reg, 0); |
arm64_ldrx(0, 1, reg, reg, 4); |
o(0xaa0083c0 | reg | reg << 16); // orr x(reg),x30,x(reg),lsl #32 |
break; |
case 7: |
arm64_ldrx(0, 2, 30, reg, 0); |
arm64_ldrx(0, 2, reg, reg, 3); |
o(0x53087c00 | reg | reg << 5); // lsr w(reg), w(reg), #8 |
o(0xaa0083c0 | reg | reg << 16); // orr x(reg),x30,x(reg),lsl #32 |
break; |
case 8: |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 9: |
arm64_ldrx(0, 0, reg + 1, reg, 8); |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 10: |
arm64_ldrx(0, 1, reg + 1, reg, 8); |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 11: |
arm64_ldrx(0, 2, reg + 1, reg, 7); |
o(0x53087c00 | (reg+1) | (reg+1) << 5); // lsr w(reg+1), w(reg+1), #8 |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 12: |
arm64_ldrx(0, 2, reg + 1, reg, 8); |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 13: |
arm64_ldrx(0, 3, reg + 1, reg, 5); |
o(0xd358fc00 | (reg+1) | (reg+1) << 5); // lsr x(reg+1), x(reg+1), #24 |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 14: |
arm64_ldrx(0, 3, reg + 1, reg, 6); |
o(0xd350fc00 | (reg+1) | (reg+1) << 5); // lsr x(reg+1), x(reg+1), #16 |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 15: |
arm64_ldrx(0, 3, reg + 1, reg, 7); |
o(0xd348fc00 | (reg+1) | (reg+1) << 5); // lsr x(reg+1), x(reg+1), #8 |
arm64_ldrx(0, 3, reg, reg, 0); |
break; |
case 16: |
o(0xa9400000 | reg | (reg+1) << 10 | reg << 5); |
// ldp x(reg),x(reg+1),[x(reg)] |
break; |
} |
} |
static void arm64_strx(int sz_, int dst, int bas, uint64_t off) |
{ |
uint32_t sz = sz_; |
if (!(off & ~((uint32_t)0xfff << sz))) |
o(0x39000000 | dst | bas << 5 | off << (10 - sz) | sz << 30); |
// str(*) x(dst),[x(bas],#(off)] |
else if (off < 256 || -off <= 256) |
o(0x38000000 | dst | bas << 5 | (off & 511) << 12 | sz << 30); |
// stur(*) x(dst),[x(bas],#(off)] |
else { |
arm64_movimm(30, off); // use x30 for offset |
o(0x38206800 | dst | bas << 5 | (uint32_t)30 << 16 | sz << 30); |
// str(*) x(dst),[x(bas),x30] |
} |
} |
static void arm64_strv(int sz_, int dst, int bas, uint64_t off) |
{ |
uint32_t sz = sz_; |
if (!(off & ~((uint32_t)0xfff << sz))) |
o(0x3d000000 | dst | bas << 5 | off << (10 - sz) | |
(sz & 4) << 21 | (sz & 3) << 30); // str (s|d|q)(dst),[x(bas),#(off)] |
else if (off < 256 || -off <= 256) |
o(0x3c000000 | dst | bas << 5 | (off & 511) << 12 | |
(sz & 4) << 21 | (sz & 3) << 30); // stur (s|d|q)(dst),[x(bas),#(off)] |
else { |
arm64_movimm(30, off); // use x30 for offset |
o(0x3c206800 | dst | bas << 5 | (uint32_t)30 << 16 | |
sz << 30 | (sz & 4) << 21); // str (s|d|q)(dst),[x(bas),x30] |
} |
} |
static void arm64_sym(int r, Sym *sym, unsigned long addend) |
{ |
// Currently TCC's linker does not generate COPY relocations for |
// STT_OBJECTs when tcc is invoked with "-run". This typically |
// results in "R_AARCH64_ADR_PREL_PG_HI21 relocation failed" when |
// a program refers to stdin. A workaround is to avoid that |
// relocation and use only relocations with unlimited range. |
int avoid_adrp = 1; |
if (avoid_adrp || (sym->type.t & VT_WEAK)) { |
// (GCC uses a R_AARCH64_ABS64 in this case.) |
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend); |
o(0xd2800000 | r); // mov x(rt),#0,lsl #0 |
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G1_NC, addend); |
o(0xf2a00000 | r); // movk x(rt),#0,lsl #16 |
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G2_NC, addend); |
o(0xf2c00000 | r); // movk x(rt),#0,lsl #32 |
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G3, addend); |
o(0xf2e00000 | r); // movk x(rt),#0,lsl #48 |
} |
else { |
greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, addend); |
o(0x90000000 | r); |
greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, addend); |
o(0x91000000 | r | r << 5); |
} |
} |
ST_FUNC void load(int r, SValue *sv) |
{ |
int svtt = sv->type.t; |
int svr = sv->r & ~VT_LVAL_TYPE; |
int svrv = svr & VT_VALMASK; |
uint64_t svcul = (uint32_t)sv->c.i; |
svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul; |
if (svr == (VT_LOCAL | VT_LVAL)) { |
if (IS_FREG(r)) |
arm64_ldrv(arm64_type_size(svtt), fltr(r), 29, svcul); |
else |
arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), |
intr(r), 29, svcul); |
return; |
} |
if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { |
if (IS_FREG(r)) |
arm64_ldrv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); |
else |
arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), |
intr(r), intr(svrv), 0); |
return; |
} |
if (svr == (VT_CONST | VT_LVAL | VT_SYM)) { |
arm64_sym(30, sv->sym, svcul); // use x30 for address |
if (IS_FREG(r)) |
arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, 0); |
else |
arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), |
intr(r), 30, 0); |
return; |
} |
if (svr == (VT_CONST | VT_SYM)) { |
arm64_sym(intr(r), sv->sym, svcul); |
return; |
} |
if (svr == VT_CONST) { |
if ((svtt & VT_BTYPE) != VT_VOID) |
arm64_movimm(intr(r), arm64_type_size(svtt) == 3 ? |
sv->c.i : (uint32_t)svcul); |
return; |
} |
if (svr < VT_CONST) { |
if (IS_FREG(r) && IS_FREG(svr)) |
if (svtt == VT_LDOUBLE) |
o(0x4ea01c00 | fltr(r) | fltr(svr) << 5); |
// mov v(r).16b,v(svr).16b |
else |
o(0x1e604000 | fltr(r) | fltr(svr) << 5); // fmov d(r),d(svr) |
else if (!IS_FREG(r) && !IS_FREG(svr)) |
o(0xaa0003e0 | intr(r) | intr(svr) << 16); // mov x(r),x(svr) |
else |
assert(0); |
return; |
} |
if (svr == VT_LOCAL) { |
if (-svcul < 0x1000) |
o(0xd10003a0 | intr(r) | -svcul << 10); // sub x(r),x29,#... |
else { |
arm64_movimm(30, -svcul); // use x30 for offset |
o(0xcb0003a0 | intr(r) | (uint32_t)30 << 16); // sub x(r),x29,x30 |
} |
return; |
} |
if (svr == VT_JMP || svr == VT_JMPI) { |
int t = (svr == VT_JMPI); |
arm64_movimm(intr(r), t); |
o(0x14000002); // b .+8 |
gsym(svcul); |
arm64_movimm(intr(r), t ^ 1); |
return; |
} |
if (svr == (VT_LLOCAL | VT_LVAL)) { |
arm64_ldrx(0, 3, 30, 29, svcul); // use x30 for offset |
if (IS_FREG(r)) |
arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, 0); |
else |
arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), |
intr(r), 30, 0); |
return; |
} |
printf("load(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul); |
assert(0); |
} |
ST_FUNC void store(int r, SValue *sv) |
{ |
int svtt = sv->type.t; |
int svr = sv->r & ~VT_LVAL_TYPE; |
int svrv = svr & VT_VALMASK; |
uint64_t svcul = (uint32_t)sv->c.i; |
svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul; |
if (svr == (VT_LOCAL | VT_LVAL)) { |
if (IS_FREG(r)) |
arm64_strv(arm64_type_size(svtt), fltr(r), 29, svcul); |
else |
arm64_strx(arm64_type_size(svtt), intr(r), 29, svcul); |
return; |
} |
if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { |
if (IS_FREG(r)) |
arm64_strv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); |
else |
arm64_strx(arm64_type_size(svtt), intr(r), intr(svrv), 0); |
return; |
} |
if (svr == (VT_CONST | VT_LVAL | VT_SYM)) { |
arm64_sym(30, sv->sym, svcul); // use x30 for address |
if (IS_FREG(r)) |
arm64_strv(arm64_type_size(svtt), fltr(r), 30, 0); |
else |
arm64_strx(arm64_type_size(svtt), intr(r), 30, 0); |
return; |
} |
printf("store(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul); |
assert(0); |
} |
static void arm64_gen_bl_or_b(int b) |
{ |
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
assert(!b); |
if (vtop->r & VT_SYM) |
greloc(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26); |
else |
assert(0); |
o(0x94000000); // bl . |
} |
else |
o(0xd61f0000 | (uint32_t)!b << 21 | intr(gv(RC_R30)) << 5); // br/blr |
} |
static int arm64_hfa_aux(CType *type, int *fsize, int num) |
{ |
if (is_float(type->t)) { |
int a, n = type_size(type, &a); |
if (num >= 4 || (*fsize && *fsize != n)) |
return -1; |
*fsize = n; |
return num + 1; |
} |
else if ((type->t & VT_BTYPE) == VT_STRUCT) { |
int is_struct = 0; // rather than union |
Sym *field; |
for (field = type->ref->next; field; field = field->next) |
if (field->c) { |
is_struct = 1; |
break; |
} |
if (is_struct) { |
int num0 = num; |
for (field = type->ref->next; field; field = field->next) { |
if (field->c != (num - num0) * *fsize) |
return -1; |
num = arm64_hfa_aux(&field->type, fsize, num); |
if (num == -1) |
return -1; |
} |
if (type->ref->c != (num - num0) * *fsize) |
return -1; |
return num; |
} |
else { // union |
int num0 = num; |
for (field = type->ref->next; field; field = field->next) { |
int num1 = arm64_hfa_aux(&field->type, fsize, num0); |
if (num1 == -1) |
return -1; |
num = num1 < num ? num : num1; |
} |
if (type->ref->c != (num - num0) * *fsize) |
return -1; |
return num; |
} |
} |
else if (type->t & VT_ARRAY) { |
int num1; |
if (!type->ref->c) |
return num; |
num1 = arm64_hfa_aux(&type->ref->type, fsize, num); |
if (num1 == -1 || (num1 != num && type->ref->c > 4)) |
return -1; |
num1 = num + type->ref->c * (num1 - num); |
if (num1 > 4) |
return -1; |
return num1; |
} |
return -1; |
} |
static int arm64_hfa(CType *type, int *fsize) |
{ |
if ((type->t & VT_BTYPE) == VT_STRUCT || (type->t & VT_ARRAY)) { |
int sz = 0; |
int n = arm64_hfa_aux(type, &sz, 0); |
if (0 < n && n <= 4) { |
if (fsize) |
*fsize = sz; |
return n; |
} |
} |
return 0; |
} |
static unsigned long arm64_pcs_aux(int n, CType **type, unsigned long *a) |
{ |
int nx = 0; // next integer register |
int nv = 0; // next vector register |
unsigned long ns = 32; // next stack offset |
int i; |
for (i = 0; i < n; i++) { |
int hfa = arm64_hfa(type[i], 0); |
int size, align; |
if ((type[i]->t & VT_ARRAY) || |
(type[i]->t & VT_BTYPE) == VT_FUNC) |
size = align = 8; |
else |
size = type_size(type[i], &align); |
if (hfa) |
// B.2 |
; |
else if (size > 16) { |
// B.3: replace with pointer |
if (nx < 8) |
a[i] = nx++ << 1 | 1; |
else { |
ns = (ns + 7) & ~7; |
a[i] = ns | 1; |
ns += 8; |
} |
continue; |
} |
else if ((type[i]->t & VT_BTYPE) == VT_STRUCT) |
// B.4 |
size = (size + 7) & ~7; |
// C.1 |
if (is_float(type[i]->t) && nv < 8) { |
a[i] = 16 + (nv++ << 1); |
continue; |
} |
// C.2 |
if (hfa && nv + hfa <= 8) { |
a[i] = 16 + (nv << 1); |
nv += hfa; |
continue; |
} |
// C.3 |
if (hfa) { |
nv = 8; |
size = (size + 7) & ~7; |
} |
// C.4 |
if (hfa || (type[i]->t & VT_BTYPE) == VT_LDOUBLE) { |
ns = (ns + 7) & ~7; |
ns = (ns + align - 1) & -align; |
} |
// C.5 |
if ((type[i]->t & VT_BTYPE) == VT_FLOAT) |
size = 8; |
// C.6 |
if (hfa || is_float(type[i]->t)) { |
a[i] = ns; |
ns += size; |
continue; |
} |
// C.7 |
if ((type[i]->t & VT_BTYPE) != VT_STRUCT && size <= 8 && nx < 8) { |
a[i] = nx++ << 1; |
continue; |
} |
// C.8 |
if (align == 16) |
nx = (nx + 1) & ~1; |
// C.9 |
if ((type[i]->t & VT_BTYPE) != VT_STRUCT && size == 16 && nx < 7) { |
a[i] = nx << 1; |
nx += 2; |
continue; |
} |
// C.10 |
if ((type[i]->t & VT_BTYPE) == VT_STRUCT && size <= (8 - nx) * 8) { |
a[i] = nx << 1; |
nx += (size + 7) >> 3; |
continue; |
} |
// C.11 |
nx = 8; |
// C.12 |
ns = (ns + 7) & ~7; |
ns = (ns + align - 1) & -align; |
// C.13 |
if ((type[i]->t & VT_BTYPE) == VT_STRUCT) { |
a[i] = ns; |
ns += size; |
continue; |
} |
// C.14 |
if (size < 8) |
size = 8; |
// C.15 |
a[i] = ns; |
ns += size; |
} |
return ns - 32; |
} |
static unsigned long arm64_pcs(int n, CType **type, unsigned long *a) |
{ |
unsigned long stack; |
// Return type: |
if ((type[0]->t & VT_BTYPE) == VT_VOID) |
a[0] = -1; |
else { |
arm64_pcs_aux(1, type, a); |
assert(a[0] == 0 || a[0] == 1 || a[0] == 16); |
} |
// Argument types: |
stack = arm64_pcs_aux(n, type + 1, a + 1); |
if (0) { |
int i; |
for (i = 0; i <= n; i++) { |
if (!i) |
printf("arm64_pcs return: "); |
else |
printf("arm64_pcs arg %d: ", i); |
if (a[i] == (unsigned long)-1) |
printf("void\n"); |
else if (a[i] == 1 && !i) |
printf("X8 pointer\n"); |
else if (a[i] < 16) |
printf("X%lu%s\n", a[i] / 2, a[i] & 1 ? " pointer" : ""); |
else if (a[i] < 32) |
printf("V%lu\n", a[i] / 2 - 8); |
else |
printf("stack %lu%s\n", |
(a[i] - 32) & ~1, a[i] & 1 ? " pointer" : ""); |
} |
} |
return stack; |
} |
ST_FUNC void gfunc_call(int nb_args) |
{ |
CType *return_type; |
CType **t; |
unsigned long *a, *a1; |
unsigned long stack; |
int i; |
return_type = &vtop[-nb_args].type.ref->type; |
if ((return_type->t & VT_BTYPE) == VT_STRUCT) |
--nb_args; |
t = tcc_malloc((nb_args + 1) * sizeof(*t)); |
a = tcc_malloc((nb_args + 1) * sizeof(*a)); |
a1 = tcc_malloc((nb_args + 1) * sizeof(*a1)); |
t[0] = return_type; |
for (i = 0; i < nb_args; i++) |
t[nb_args - i] = &vtop[-i].type; |
stack = arm64_pcs(nb_args, t, a); |
// Allocate space for structs replaced by pointer: |
for (i = nb_args; i; i--) |
if (a[i] & 1) { |
SValue *arg = &vtop[i - nb_args]; |
int align, size = type_size(&arg->type, &align); |
assert((arg->type.t & VT_BTYPE) == VT_STRUCT); |
stack = (stack + align - 1) & -align; |
a1[i] = stack; |
stack += size; |
} |
stack = (stack + 15) >> 4 << 4; |
assert(stack < 0x1000); |
if (stack) |
o(0xd10003ff | stack << 10); // sub sp,sp,#(n) |
// First pass: set all values on stack |
for (i = nb_args; i; i--) { |
vpushv(vtop - nb_args + i); |
if (a[i] & 1) { |
// struct replaced by pointer |
int r = get_reg(RC_INT); |
arm64_spoff(intr(r), a1[i]); |
vset(&vtop->type, r | VT_LVAL, 0); |
vswap(); |
vstore(); |
if (a[i] >= 32) { |
// pointer on stack |
r = get_reg(RC_INT); |
arm64_spoff(intr(r), a1[i]); |
arm64_strx(3, intr(r), 31, (a[i] - 32) >> 1 << 1); |
} |
} |
else if (a[i] >= 32) { |
// value on stack |
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
int r = get_reg(RC_INT); |
arm64_spoff(intr(r), a[i] - 32); |
vset(&vtop->type, r | VT_LVAL, 0); |
vswap(); |
vstore(); |
} |
else if (is_float(vtop->type.t)) { |
gv(RC_FLOAT); |
arm64_strv(arm64_type_size(vtop[0].type.t), |
fltr(vtop[0].r), 31, a[i] - 32); |
} |
else { |
gv(RC_INT); |
arm64_strx(arm64_type_size(vtop[0].type.t), |
intr(vtop[0].r), 31, a[i] - 32); |
} |
} |
--vtop; |
} |
// Second pass: assign values to registers |
for (i = nb_args; i; i--, vtop--) { |
if (a[i] < 16 && !(a[i] & 1)) { |
// value in general-purpose registers |
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
int align, size = type_size(&vtop->type, &align); |
vtop->type.t = VT_PTR; |
gaddrof(); |
gv(RC_R(a[i] / 2)); |
arm64_ldrs(a[i] / 2, size); |
} |
else |
gv(RC_R(a[i] / 2)); |
} |
else if (a[i] < 16) |
// struct replaced by pointer in register |
arm64_spoff(a[i] / 2, a1[i]); |
else if (a[i] < 32) { |
// value in floating-point registers |
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz); |
vtop->type.t = VT_PTR; |
gaddrof(); |
gv(RC_R30); |
for (j = 0; j < n; j++) |
o(0x3d4003c0 | |
(sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 | |
(a[i] / 2 - 8 + j) | |
j << 10); // ldr ([sdq])(*),[x30,#(j * sz)] |
} |
else |
gv(RC_F(a[i] / 2 - 8)); |
} |
} |
if ((return_type->t & VT_BTYPE) == VT_STRUCT) { |
if (a[0] == 1) { |
// indirect return: set x8 and discard the stack value |
gv(RC_R(8)); |
--vtop; |
} |
else |
// return in registers: keep the address for after the call |
vswap(); |
} |
save_regs(0); |
arm64_gen_bl_or_b(0); |
--vtop; |
if (stack) |
o(0x910003ff | stack << 10); // add sp,sp,#(n) |
{ |
int rt = return_type->t; |
int bt = rt & VT_BTYPE; |
if (bt == VT_BYTE || bt == VT_SHORT) |
// Promote small integers: |
o(0x13001c00 | (bt == VT_SHORT) << 13 | |
(uint32_t)!!(rt & VT_UNSIGNED) << 30); // [su]xt[bh] w0,w0 |
else if (bt == VT_STRUCT && !(a[0] & 1)) { |
// A struct was returned in registers, so write it out: |
gv(RC_R(8)); |
--vtop; |
if (a[0] == 0) { |
int align, size = type_size(return_type, &align); |
assert(size <= 16); |
if (size > 8) |
o(0xa9000500); // stp x0,x1,[x8] |
else if (size) |
arm64_strx(size > 4 ? 3 : size > 2 ? 2 : size > 1, 0, 8, 0); |
} |
else if (a[0] == 16) { |
uint32_t j, sz, n = arm64_hfa(return_type, &sz); |
for (j = 0; j < n; j++) |
o(0x3d000100 | |
(sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 | |
(a[i] / 2 - 8 + j) | |
j << 10); // str ([sdq])(*),[x8,#(j * sz)] |
} |
} |
} |
tcc_free(a1); |
tcc_free(a); |
tcc_free(t); |
} |
static unsigned long arm64_func_va_list_stack; |
static int arm64_func_va_list_gr_offs; |
static int arm64_func_va_list_vr_offs; |
static int arm64_func_sub_sp_offset; |
ST_FUNC void gfunc_prolog(CType *func_type) |
{ |
int n = 0; |
int i = 0; |
Sym *sym; |
CType **t; |
unsigned long *a; |
// Why doesn't the caller (gen_function) set func_vt? |
func_vt = func_type->ref->type; |
func_vc = 144; // offset of where x8 is stored |
for (sym = func_type->ref; sym; sym = sym->next) |
++n; |
t = tcc_malloc(n * sizeof(*t)); |
a = tcc_malloc(n * sizeof(*a)); |
for (sym = func_type->ref; sym; sym = sym->next) |
t[i++] = &sym->type; |
arm64_func_va_list_stack = arm64_pcs(n - 1, t, a); |
o(0xa9b27bfd); // stp x29,x30,[sp,#-224]! |
o(0xad0087e0); // stp q0,q1,[sp,#16] |
o(0xad018fe2); // stp q2,q3,[sp,#48] |
o(0xad0297e4); // stp q4,q5,[sp,#80] |
o(0xad039fe6); // stp q6,q7,[sp,#112] |
o(0xa90923e8); // stp x8,x8,[sp,#144] |
o(0xa90a07e0); // stp x0,x1,[sp,#160] |
o(0xa90b0fe2); // stp x2,x3,[sp,#176] |
o(0xa90c17e4); // stp x4,x5,[sp,#192] |
o(0xa90d1fe6); // stp x6,x7,[sp,#208] |
arm64_func_va_list_gr_offs = -64; |
arm64_func_va_list_vr_offs = -128; |
for (i = 1, sym = func_type->ref->next; sym; i++, sym = sym->next) { |
int off = (a[i] < 16 ? 160 + a[i] / 2 * 8 : |
a[i] < 32 ? 16 + (a[i] - 16) / 2 * 16 : |
224 + ((a[i] - 32) >> 1 << 1)); |
sym_push(sym->v & ~SYM_FIELD, &sym->type, |
(a[i] & 1 ? VT_LLOCAL : VT_LOCAL) | lvalue_type(sym->type.t), |
off); |
if (a[i] < 16) { |
int align, size = type_size(&sym->type, &align); |
arm64_func_va_list_gr_offs = (a[i] / 2 - 7 + |
(!(a[i] & 1) && size > 8)) * 8; |
} |
else if (a[i] < 32) { |
uint32_t hfa = arm64_hfa(&sym->type, 0); |
arm64_func_va_list_vr_offs = (a[i] / 2 - 16 + |
(hfa ? hfa : 1)) * 16; |
} |
// HFAs of float and double need to be written differently: |
if (16 <= a[i] && a[i] < 32 && (sym->type.t & VT_BTYPE) == VT_STRUCT) { |
uint32_t j, sz, k = arm64_hfa(&sym->type, &sz); |
if (sz < 16) |
for (j = 0; j < k; j++) { |
o(0x3d0003e0 | -(sz & 8) << 27 | (sz & 4) << 29 | |
((a[i] - 16) / 2 + j) | (off / sz + j) << 10); |
// str ([sdq])(*),[sp,#(j * sz)] |
} |
} |
} |
tcc_free(a); |
tcc_free(t); |
o(0x910003fd); // mov x29,sp |
arm64_func_sub_sp_offset = ind; |
// In gfunc_epilog these will be replaced with code to decrement SP: |
o(0xd503201f); // nop |
o(0xd503201f); // nop |
loc = 0; |
} |
ST_FUNC void gen_va_start(void) |
{ |
int r; |
--vtop; // we don't need the "arg" |
gaddrof(); |
r = intr(gv(RC_INT)); |
if (arm64_func_va_list_stack) { |
//xx could use add (immediate) here |
arm64_movimm(30, arm64_func_va_list_stack + 224); |
o(0x8b1e03be); // add x30,x29,x30 |
} |
else |
o(0x910383be); // add x30,x29,#224 |
o(0xf900001e | r << 5); // str x30,[x(r)] |
if (arm64_func_va_list_gr_offs) { |
if (arm64_func_va_list_stack) |
o(0x910383be); // add x30,x29,#224 |
o(0xf900041e | r << 5); // str x30,[x(r),#8] |
} |
if (arm64_func_va_list_vr_offs) { |
o(0x910243be); // add x30,x29,#144 |
o(0xf900081e | r << 5); // str x30,[x(r),#16] |
} |
arm64_movimm(30, arm64_func_va_list_gr_offs); |
o(0xb900181e | r << 5); // str w30,[x(r),#24] |
arm64_movimm(30, arm64_func_va_list_vr_offs); |
o(0xb9001c1e | r << 5); // str w30,[x(r),#28] |
--vtop; |
} |
ST_FUNC void gen_va_arg(CType *t) |
{ |
int align, size = type_size(t, &align); |
int fsize, hfa = arm64_hfa(t, &fsize); |
uint32_t r0, r1; |
if (is_float(t->t)) { |
hfa = 1; |
fsize = size; |
} |
gaddrof(); |
r0 = intr(gv(RC_INT)); |
r1 = get_reg(RC_INT); |
vtop[0].r = r1 | lvalue_type(t->t); |
r1 = intr(r1); |
if (!hfa) { |
uint32_t n = size > 16 ? 8 : (size + 7) & -8; |
o(0xb940181e | r0 << 5); // ldr w30,[x(r0),#24] // __gr_offs |
if (align == 16) { |
assert(0); // this path untested but needed for __uint128_t |
o(0x11003fde); // add w30,w30,#15 |
o(0x121c6fde); // and w30,w30,#-16 |
} |
o(0x310003c0 | r1 | n << 10); // adds w(r1),w30,#(n) |
o(0x540000ad); // b.le .+20 |
o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack |
o(0x9100001e | r1 << 5 | n << 10); // add x30,x(r1),#(n) |
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack |
o(0x14000004); // b .+16 |
o(0xb9001800 | r1 | r0 << 5); // str w(r1),[x(r0),#24] // __gr_offs |
o(0xf9400400 | r1 | r0 << 5); // ldr x(r1),[x(r0),#8] // __gr_top |
o(0x8b3ec000 | r1 | r1 << 5); // add x(r1),x(r1),w30,sxtw |
if (size > 16) |
o(0xf9400000 | r1 | r1 << 5); // ldr x(r1),[x(r1)] |
} |
else { |
uint32_t rsz = hfa << 4; |
uint32_t ssz = (size + 7) & -(uint32_t)8; |
uint32_t b1, b2; |
o(0xb9401c1e | r0 << 5); // ldr w30,[x(r0),#28] // __vr_offs |
o(0x310003c0 | r1 | rsz << 10); // adds w(r1),w30,#(rsz) |
b1 = ind; o(0x5400000d); // b.le lab1 |
o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack |
if (fsize == 16) { |
o(0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15 |
o(0x927cec00 | r1 | r1 << 5); // and x(r1),x(r1),#-16 |
} |
o(0x9100001e | r1 << 5 | ssz << 10); // add x30,x(r1),#(ssz) |
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack |
b2 = ind; o(0x14000000); // b lab2 |
// lab1: |
write32le(cur_text_section->data + b1, 0x5400000d | (ind - b1) << 3); |
o(0xb9001c00 | r1 | r0 << 5); // str w(r1),[x(r0),#28] // __vr_offs |
o(0xf9400800 | r1 | r0 << 5); // ldr x(r1),[x(r0),#16] // __vr_top |
if (hfa == 1 || fsize == 16) |
o(0x8b3ec000 | r1 | r1 << 5); // add x(r1),x(r1),w30,sxtw |
else { |
// We need to change the layout of this HFA. |
// Get some space on the stack using global variable "loc": |
loc = (loc - size) & -(uint32_t)align; |
o(0x8b3ec000 | 30 | r1 << 5); // add x30,x(r1),w30,sxtw |
arm64_movimm(r1, loc); |
o(0x8b0003a0 | r1 | r1 << 16); // add x(r1),x29,x(r1) |
o(0x4c402bdc | (uint32_t)fsize << 7 | |
(uint32_t)(hfa == 2) << 15 | |
(uint32_t)(hfa == 3) << 14); // ld1 {v28.(4s|2d),...},[x30] |
o(0x0d00801c | r1 << 5 | (fsize == 8) << 10 | |
(uint32_t)(hfa != 2) << 13 | |
(uint32_t)(hfa != 3) << 21); // st(hfa) {v28.(s|d),...}[0],[x(r1)] |
} |
// lab2: |
write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2); |
} |
} |
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, |
int *align, int *regsize) |
{ |
return 0; |
} |
ST_FUNC void greturn(void) |
{ |
CType *t = &func_vt; |
unsigned long a; |
arm64_pcs(0, &t, &a); |
switch (a) { |
case -1: |
break; |
case 0: |
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { |
int align, size = type_size(&func_vt, &align); |
gaddrof(); |
gv(RC_R(0)); |
arm64_ldrs(0, size); |
} |
else |
gv(RC_IRET); |
break; |
case 1: { |
CType type = func_vt; |
mk_pointer(&type); |
vset(&type, VT_LOCAL | VT_LVAL, func_vc); |
indir(); |
vswap(); |
vstore(); |
break; |
} |
case 16: |
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { |
uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz); |
gaddrof(); |
gv(RC_R(0)); |
for (j = 0; j < n; j++) |
o(0x3d400000 | |
(sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 | |
j | j << 10); // ldr ([sdq])(*),[x0,#(j * sz)] |
} |
else |
gv(RC_FRET); |
break; |
default: |
assert(0); |
} |
} |
ST_FUNC void gfunc_epilog(void) |
{ |
if (loc) { |
// Insert instructions to subtract size of stack frame from SP. |
unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset; |
uint64_t diff = (-loc + 15) & ~15; |
if (!(diff >> 24)) { |
if (diff & 0xfff) // sub sp,sp,#(diff & 0xfff) |
write32le(ptr, 0xd10003ff | (diff & 0xfff) << 10); |
if (diff >> 12) // sub sp,sp,#(diff >> 12),lsl #12 |
write32le(ptr + 4, 0xd14003ff | (diff >> 12) << 10); |
} |
else { |
// In this case we may subtract more than necessary, |
// but always less than 17/16 of what we were aiming for. |
int i = 0; |
int j = 0; |
while (diff >> 20) { |
diff = (diff + 0xffff) >> 16; |
++i; |
} |
while (diff >> 16) { |
diff = (diff + 1) >> 1; |
++j; |
} |
write32le(ptr, 0xd2800010 | diff << 5 | i << 21); |
// mov x16,#(diff),lsl #(16 * i) |
write32le(ptr + 4, 0xcb3063ff | j << 10); |
// sub sp,sp,x16,lsl #(j) |
} |
} |
o(0x910003bf); // mov sp,x29 |
o(0xa8ce7bfd); // ldp x29,x30,[sp],#224 |
o(0xd65f03c0); // ret |
} |
// Generate forward branch to label: |
ST_FUNC int gjmp(int t) |
{ |
int r = ind; |
o(t); |
return r; |
} |
// Generate branch to known address: |
ST_FUNC void gjmp_addr(int a) |
{ |
assert(a - ind + 0x8000000 < 0x10000000); |
o(0x14000000 | ((a - ind) >> 2 & 0x3ffffff)); |
} |
ST_FUNC int gtst(int inv, int t) |
{ |
int bt = vtop->type.t & VT_BTYPE; |
if (bt == VT_LDOUBLE) { |
uint32_t a, b, f = fltr(gv(RC_FLOAT)); |
a = get_reg(RC_INT); |
vpushi(0); |
vtop[0].r = a; |
b = get_reg(RC_INT); |
a = intr(a); |
b = intr(b); |
o(0x4e083c00 | a | f << 5); // mov x(a),v(f).d[0] |
o(0x4e183c00 | b | f << 5); // mov x(b),v(f).d[1] |
o(0xaa000400 | a | a << 5 | b << 16); // orr x(a),x(a),x(b),lsl #1 |
o(0xb4000040 | a | !!inv << 24); // cbz/cbnz x(a),.+8 |
--vtop; |
} |
else if (bt == VT_FLOAT || bt == VT_DOUBLE) { |
uint32_t a = fltr(gv(RC_FLOAT)); |
o(0x1e202008 | a << 5 | (bt != VT_FLOAT) << 22); // fcmp |
o(0x54000040 | !!inv); // b.eq/b.ne .+8 |
} |
else { |
uint32_t ll = (bt == VT_PTR || bt == VT_LLONG); |
uint32_t a = intr(gv(RC_INT)); |
o(0x34000040 | a | !!inv << 24 | ll << 31); // cbz/cbnz wA,.+8 |
} |
--vtop; |
return gjmp(t); |
} |
static int arm64_iconst(uint64_t *val, SValue *sv) |
{ |
if ((sv->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
return 0; |
if (val) { |
int t = sv->type.t; |
*val = ((t & VT_BTYPE) == VT_LLONG ? sv->c.i : |
(uint32_t)sv->c.i | |
(t & VT_UNSIGNED ? 0 : -(sv->c.i & 0x80000000))); |
} |
return 1; |
} |
static int arm64_gen_opic(int op, uint32_t l, int rev, uint64_t val, |
uint32_t x, uint32_t a) |
{ |
if (op == '-' && !rev) { |
val = -val; |
op = '+'; |
} |
val = l ? val : (uint32_t)val; |
switch (op) { |
case '+': { |
uint32_t s = l ? val >> 63 : val >> 31; |
val = s ? -val : val; |
val = l ? val : (uint32_t)val; |
if (!(val & ~(uint64_t)0xfff)) |
o(0x11000000 | l << 31 | s << 30 | x | a << 5 | val << 10); |
else if (!(val & ~(uint64_t)0xfff000)) |
o(0x11400000 | l << 31 | s << 30 | x | a << 5 | val >> 12 << 10); |
else { |
arm64_movimm(30, val); // use x30 |
o(0x0b1e0000 | l << 31 | s << 30 | x | a << 5); |
} |
return 1; |
} |
case '-': |
if (!val) |
o(0x4b0003e0 | l << 31 | x | a << 16); // neg |
else if (val == (l ? (uint64_t)-1 : (uint32_t)-1)) |
o(0x2a2003e0 | l << 31 | x | a << 16); // mvn |
else { |
arm64_movimm(30, val); // use x30 |
o(0x4b0003c0 | l << 31 | x | a << 16); // sub |
} |
return 1; |
case '^': |
if (val == -1 || (val == 0xffffffff && !l)) { |
o(0x2a2003e0 | l << 31 | x | a << 16); // mvn |
return 1; |
} |
// fall through |
case '&': |
case '|': { |
int e = arm64_encode_bimm64(l ? val : val | val << 32); |
if (e < 0) |
return 0; |
o((op == '&' ? 0x12000000 : |
op == '|' ? 0x32000000 : 0x52000000) | |
l << 31 | x | a << 5 | (uint32_t)e << 10); |
return 1; |
} |
case TOK_SAR: |
case TOK_SHL: |
case TOK_SHR: { |
uint32_t n = 32 << l; |
val = val & (n - 1); |
if (rev) |
return 0; |
if (!val) |
assert(0); |
else if (op == TOK_SHL) |
o(0x53000000 | l << 31 | l << 22 | x | a << 5 | |
(n - val) << 16 | (n - 1 - val) << 10); // lsl |
else |
o(0x13000000 | (op == TOK_SHR) << 30 | l << 31 | l << 22 | |
x | a << 5 | val << 16 | (n - 1) << 10); // lsr/asr |
return 1; |
} |
} |
return 0; |
} |
static void arm64_gen_opil(int op, uint32_t l) |
{ |
uint32_t x, a, b; |
// Special treatment for operations with a constant operand: |
{ |
uint64_t val; |
int rev = 1; |
if (arm64_iconst(0, &vtop[0])) { |
vswap(); |
rev = 0; |
} |
if (arm64_iconst(&val, &vtop[-1])) { |
gv(RC_INT); |
a = intr(vtop[0].r); |
--vtop; |
x = get_reg(RC_INT); |
++vtop; |
if (arm64_gen_opic(op, l, rev, val, intr(x), a)) { |
vtop[0].r = x; |
vswap(); |
--vtop; |
return; |
} |
} |
if (!rev) |
vswap(); |
} |
gv2(RC_INT, RC_INT); |
assert(vtop[-1].r < VT_CONST && vtop[0].r < VT_CONST); |
a = intr(vtop[-1].r); |
b = intr(vtop[0].r); |
vtop -= 2; |
x = get_reg(RC_INT); |
++vtop; |
vtop[0].r = x; |
x = intr(x); |
switch (op) { |
case '%': |
// Use x30 for quotient: |
o(0x1ac00c00 | l << 31 | 30 | a << 5 | b << 16); // sdiv |
o(0x1b008000 | l << 31 | x | (uint32_t)30 << 5 | |
b << 16 | a << 10); // msub |
break; |
case '&': |
o(0x0a000000 | l << 31 | x | a << 5 | b << 16); // and |
break; |
case '*': |
o(0x1b007c00 | l << 31 | x | a << 5 | b << 16); // mul |
break; |
case '+': |
o(0x0b000000 | l << 31 | x | a << 5 | b << 16); // add |
break; |
case '-': |
o(0x4b000000 | l << 31 | x | a << 5 | b << 16); // sub |
break; |
case '/': |
o(0x1ac00c00 | l << 31 | x | a << 5 | b << 16); // sdiv |
break; |
case '^': |
o(0x4a000000 | l << 31 | x | a << 5 | b << 16); // eor |
break; |
case '|': |
o(0x2a000000 | l << 31 | x | a << 5 | b << 16); // orr |
break; |
case TOK_EQ: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9f17e0 | x); // cset wA,eq |
break; |
case TOK_GE: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9fb7e0 | x); // cset wA,ge |
break; |
case TOK_GT: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9fd7e0 | x); // cset wA,gt |
break; |
case TOK_LE: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9fc7e0 | x); // cset wA,le |
break; |
case TOK_LT: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9fa7e0 | x); // cset wA,lt |
break; |
case TOK_NE: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9f07e0 | x); // cset wA,ne |
break; |
case TOK_SAR: |
o(0x1ac02800 | l << 31 | x | a << 5 | b << 16); // asr |
break; |
case TOK_SHL: |
o(0x1ac02000 | l << 31 | x | a << 5 | b << 16); // lsl |
break; |
case TOK_SHR: |
o(0x1ac02400 | l << 31 | x | a << 5 | b << 16); // lsr |
break; |
case TOK_UDIV: |
case TOK_PDIV: |
o(0x1ac00800 | l << 31 | x | a << 5 | b << 16); // udiv |
break; |
case TOK_UGE: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9f37e0 | x); // cset wA,cs |
break; |
case TOK_UGT: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9f97e0 | x); // cset wA,hi |
break; |
case TOK_ULT: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9f27e0 | x); // cset wA,cc |
break; |
case TOK_ULE: |
o(0x6b00001f | l << 31 | a << 5 | b << 16); // cmp |
o(0x1a9f87e0 | x); // cset wA,ls |
break; |
case TOK_UMOD: |
// Use x30 for quotient: |
o(0x1ac00800 | l << 31 | 30 | a << 5 | b << 16); // udiv |
o(0x1b008000 | l << 31 | x | (uint32_t)30 << 5 | |
b << 16 | a << 10); // msub |
break; |
default: |
assert(0); |
} |
} |
ST_FUNC void gen_opi(int op) |
{ |
arm64_gen_opil(op, 0); |
} |
ST_FUNC void gen_opl(int op) |
{ |
arm64_gen_opil(op, 1); |
} |
ST_FUNC void gen_opf(int op) |
{ |
uint32_t x, a, b, dbl; |
if (vtop[0].type.t == VT_LDOUBLE) { |
CType type = vtop[0].type; |
int func = 0; |
int cond = -1; |
switch (op) { |
case '*': func = TOK___multf3; break; |
case '+': func = TOK___addtf3; break; |
case '-': func = TOK___subtf3; break; |
case '/': func = TOK___divtf3; break; |
case TOK_EQ: func = TOK___eqtf2; cond = 1; break; |
case TOK_NE: func = TOK___netf2; cond = 0; break; |
case TOK_LT: func = TOK___lttf2; cond = 10; break; |
case TOK_GE: func = TOK___getf2; cond = 11; break; |
case TOK_LE: func = TOK___letf2; cond = 12; break; |
case TOK_GT: func = TOK___gttf2; cond = 13; break; |
default: assert(0); break; |
} |
vpush_global_sym(&func_old_type, func); |
vrott(3); |
gfunc_call(2); |
vpushi(0); |
vtop->r = cond < 0 ? REG_FRET : REG_IRET; |
if (cond < 0) |
vtop->type = type; |
else { |
o(0x7100001f); // cmp w0,#0 |
o(0x1a9f07e0 | (uint32_t)cond << 12); // cset w0,(cond) |
} |
return; |
} |
dbl = vtop[0].type.t != VT_FLOAT; |
gv2(RC_FLOAT, RC_FLOAT); |
assert(vtop[-1].r < VT_CONST && vtop[0].r < VT_CONST); |
a = fltr(vtop[-1].r); |
b = fltr(vtop[0].r); |
vtop -= 2; |
switch (op) { |
case TOK_EQ: case TOK_NE: |
case TOK_LT: case TOK_GE: case TOK_LE: case TOK_GT: |
x = get_reg(RC_INT); |
++vtop; |
vtop[0].r = x; |
x = intr(x); |
break; |
default: |
x = get_reg(RC_FLOAT); |
++vtop; |
vtop[0].r = x; |
x = fltr(x); |
break; |
} |
switch (op) { |
case '*': |
o(0x1e200800 | dbl << 22 | x | a << 5 | b << 16); // fmul |
break; |
case '+': |
o(0x1e202800 | dbl << 22 | x | a << 5 | b << 16); // fadd |
break; |
case '-': |
o(0x1e203800 | dbl << 22 | x | a << 5 | b << 16); // fsub |
break; |
case '/': |
o(0x1e201800 | dbl << 22 | x | a << 5 | b << 16); // fdiv |
break; |
case TOK_EQ: |
o(0x1e202000 | dbl << 22 | a << 5 | b << 16); // fcmp |
o(0x1a9f17e0 | x); // cset w(x),eq |
break; |
case TOK_GE: |
o(0x1e202000 | dbl << 22 | a << 5 | b << 16); // fcmp |
o(0x1a9fb7e0 | x); // cset w(x),ge |
break; |
case TOK_GT: |
o(0x1e202000 | dbl << 22 | a << 5 | b << 16); // fcmp |
o(0x1a9fd7e0 | x); // cset w(x),gt |
break; |
case TOK_LE: |
o(0x1e202000 | dbl << 22 | a << 5 | b << 16); // fcmp |
o(0x1a9f87e0 | x); // cset w(x),ls |
break; |
case TOK_LT: |
o(0x1e202000 | dbl << 22 | a << 5 | b << 16); // fcmp |
o(0x1a9f57e0 | x); // cset w(x),mi |
break; |
case TOK_NE: |
o(0x1e202000 | dbl << 22 | a << 5 | b << 16); // fcmp |
o(0x1a9f07e0 | x); // cset w(x),ne |
break; |
default: |
assert(0); |
} |
} |
// Generate sign extension from 32 to 64 bits: |
ST_FUNC void gen_cvt_sxtw(void) |
{ |
uint32_t r = intr(gv(RC_INT)); |
o(0x93407c00 | r | r << 5); // sxtw x(r),w(r) |
} |
ST_FUNC void gen_cvt_itof(int t) |
{ |
if (t == VT_LDOUBLE) { |
int f = vtop->type.t; |
int func = (f & VT_BTYPE) == VT_LLONG ? |
(f & VT_UNSIGNED ? TOK___floatunditf : TOK___floatditf) : |
(f & VT_UNSIGNED ? TOK___floatunsitf : TOK___floatsitf); |
vpush_global_sym(&func_old_type, func); |
vrott(2); |
gfunc_call(1); |
vpushi(0); |
vtop->type.t = t; |
vtop->r = REG_FRET; |
return; |
} |
else { |
int d, n = intr(gv(RC_INT)); |
int s = !(vtop->type.t & VT_UNSIGNED); |
uint32_t l = ((vtop->type.t & VT_BTYPE) == VT_LLONG); |
--vtop; |
d = get_reg(RC_FLOAT); |
++vtop; |
vtop[0].r = d; |
o(0x1e220000 | (uint32_t)!s << 16 | |
(uint32_t)(t != VT_FLOAT) << 22 | fltr(d) | |
l << 31 | n << 5); // [us]cvtf [sd](d),[wx](n) |
} |
} |
ST_FUNC void gen_cvt_ftoi(int t) |
{ |
if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { |
int func = (t & VT_BTYPE) == VT_LLONG ? |
(t & VT_UNSIGNED ? TOK___fixunstfdi : TOK___fixtfdi) : |
(t & VT_UNSIGNED ? TOK___fixunstfsi : TOK___fixtfsi); |
vpush_global_sym(&func_old_type, func); |
vrott(2); |
gfunc_call(1); |
vpushi(0); |
vtop->type.t = t; |
vtop->r = REG_IRET; |
return; |
} |
else { |
int d, n = fltr(gv(RC_FLOAT)); |
uint32_t l = ((vtop->type.t & VT_BTYPE) != VT_FLOAT); |
--vtop; |
d = get_reg(RC_INT); |
++vtop; |
vtop[0].r = d; |
o(0x1e380000 | |
(uint32_t)!!(t & VT_UNSIGNED) << 16 | |
(uint32_t)((t & VT_BTYPE) == VT_LLONG) << 31 | intr(d) | |
l << 22 | n << 5); // fcvtz[su] [wx](d),[sd](n) |
} |
} |
ST_FUNC void gen_cvt_ftof(int t) |
{ |
int f = vtop[0].type.t; |
assert(t == VT_FLOAT || t == VT_DOUBLE || t == VT_LDOUBLE); |
assert(f == VT_FLOAT || f == VT_DOUBLE || f == VT_LDOUBLE); |
if (t == f) |
return; |
if (t == VT_LDOUBLE || f == VT_LDOUBLE) { |
int func = (t == VT_LDOUBLE) ? |
(f == VT_FLOAT ? TOK___extendsftf2 : TOK___extenddftf2) : |
(t == VT_FLOAT ? TOK___trunctfsf2 : TOK___trunctfdf2); |
vpush_global_sym(&func_old_type, func); |
vrott(2); |
gfunc_call(1); |
vpushi(0); |
vtop->type.t = t; |
vtop->r = REG_FRET; |
} |
else { |
int x, a; |
gv(RC_FLOAT); |
assert(vtop[0].r < VT_CONST); |
a = fltr(vtop[0].r); |
--vtop; |
x = get_reg(RC_FLOAT); |
++vtop; |
vtop[0].r = x; |
x = fltr(x); |
if (f == VT_FLOAT) |
o(0x1e22c000 | x | a << 5); // fcvt d(x),s(a) |
else |
o(0x1e624000 | x | a << 5); // fcvt s(x),d(a) |
} |
} |
ST_FUNC void ggoto(void) |
{ |
arm64_gen_bl_or_b(1); |
--vtop; |
} |
ST_FUNC void gen_clear_cache(void) |
{ |
uint32_t beg, end, dsz, isz, p, lab1, b1; |
gv2(RC_INT, RC_INT); |
vpushi(0); |
vtop->r = get_reg(RC_INT); |
vpushi(0); |
vtop->r = get_reg(RC_INT); |
vpushi(0); |
vtop->r = get_reg(RC_INT); |
beg = intr(vtop[-4].r); // x0 |
end = intr(vtop[-3].r); // x1 |
dsz = intr(vtop[-2].r); // x2 |
isz = intr(vtop[-1].r); // x3 |
p = intr(vtop[0].r); // x4 |
vtop -= 5; |
o(0xd53b0020 | isz); // mrs x(isz),ctr_el0 |
o(0x52800080 | p); // mov w(p),#4 |
o(0x53104c00 | dsz | isz << 5); // ubfx w(dsz),w(isz),#16,#4 |
o(0x1ac02000 | dsz | p << 5 | dsz << 16); // lsl w(dsz),w(p),w(dsz) |
o(0x12000c00 | isz | isz << 5); // and w(isz),w(isz),#15 |
o(0x1ac02000 | isz | p << 5 | isz << 16); // lsl w(isz),w(p),w(isz) |
o(0x51000400 | p | dsz << 5); // sub w(p),w(dsz),#1 |
o(0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p) |
b1 = ind; o(0x14000000); // b |
lab1 = ind; |
o(0xd50b7b20 | p); // dc cvau,x(p) |
o(0x8b000000 | p | p << 5 | dsz << 16); // add x(p),x(p),x(dsz) |
write32le(cur_text_section->data + b1, 0x14000000 | (ind - b1) >> 2); |
o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end) |
o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1 |
o(0xd5033b9f); // dsb ish |
o(0x51000400 | p | isz << 5); // sub w(p),w(isz),#1 |
o(0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p) |
b1 = ind; o(0x14000000); // b |
lab1 = ind; |
o(0xd50b7520 | p); // ic ivau,x(p) |
o(0x8b000000 | p | p << 5 | isz << 16); // add x(p),x(p),x(isz) |
write32le(cur_text_section->data + b1, 0x14000000 | (ind - b1) >> 2); |
o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end) |
o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1 |
o(0xd5033b9f); // dsb ish |
o(0xd5033fdf); // isb |
} |
ST_FUNC void gen_vla_sp_save(int addr) { |
uint32_t r = intr(get_reg(RC_INT)); |
o(0x910003e0 | r); // mov x(r),sp |
arm64_strx(3, r, 29, addr); |
} |
ST_FUNC void gen_vla_sp_restore(int addr) { |
uint32_t r = intr(get_reg(RC_INT)); |
arm64_ldrx(0, 3, r, 29, addr); |
o(0x9100001f | r << 5); // mov sp,x(r) |
} |
ST_FUNC void gen_vla_alloc(CType *type, int align) { |
uint32_t r = intr(gv(RC_INT)); |
o(0x91003c00 | r | r << 5); // add x(r),x(r),#15 |
o(0x927cec00 | r | r << 5); // bic x(r),x(r),#15 |
o(0xcb2063ff | r << 16); // sub sp,sp,x(r) |
vpop(); |
} |
/* end of A64 code generator */ |
/*************************************************************/ |
#endif |
/*************************************************************/ |
/programs/develop/ktcc/trunk/source/c67-gen.c |
---|
18,8 → 18,10 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
//#define ASSEMBLY_LISTING_C67 |
#ifdef TARGET_DEFS_ONLY |
/* #define ASSEMBLY_LISTING_C67 */ |
/* number of available registers */ |
#define NB_REGS 24 |
85,7 → 87,47 |
TREG_C67_B13, |
}; |
int reg_classes[NB_REGS] = { |
/* return registers for function */ |
#define REG_IRET TREG_C67_A4 /* single word int return register */ |
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */ |
#define REG_FRET TREG_C67_A4 /* float return register */ |
/* defined if function parameters must be evaluated in reverse order */ |
/* #define INVERT_FUNC_PARAMS */ |
/* defined if structures are passed as pointers. Otherwise structures |
are directly pushed on stack. */ |
/* #define FUNC_STRUCT_PARAM_AS_PTR */ |
/* pointer size, in bytes */ |
#define PTR_SIZE 4 |
/* long double size and alignment, in bytes */ |
#define LDOUBLE_SIZE 12 |
#define LDOUBLE_ALIGN 4 |
/* maximum alignment (for aligned attribute support) */ |
#define MAX_ALIGN 8 |
/******************************************************/ |
/* ELF defines */ |
#define EM_TCC_TARGET EM_C60 |
/* relocation type for 32 bit data relocation */ |
#define R_DATA_32 R_C60_32 |
#define R_DATA_PTR R_C60_32 |
#define R_JMP_SLOT R_C60_JMP_SLOT |
#define R_COPY R_C60_COPY |
#define ELF_START_ADDR 0x00000400 |
#define ELF_PAGE_SIZE 0x1000 |
/******************************************************/ |
#else /* ! TARGET_DEFS_ONLY */ |
/******************************************************/ |
#include "tcc.h" |
ST_DATA const int reg_classes[NB_REGS] = { |
/* eax */ RC_INT | RC_FLOAT | RC_EAX, |
// only allow even regs for floats (allow for doubles) |
/* ecx */ RC_INT | RC_ECX, |
114,18 → 156,6 |
/* B13 */ RC_C67_B11 |
}; |
/* return registers for function */ |
#define REG_IRET TREG_C67_A4 /* single word int return register */ |
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */ |
#define REG_FRET TREG_C67_A4 /* float return register */ |
#define ALWAYS_ASSERT(x) \ |
do {\ |
if (!(x))\ |
error("internal compiler error file at %s:%d", __FILE__, __LINE__);\ |
} while (0) |
// although tcc thinks it is passing parameters on the stack, |
// the C67 really passes up to the first 10 params in special |
// regs or regs pairs (for 64 bit params). So keep track of |
132,7 → 162,6 |
// the stack offsets so we can translate to the appropriate |
// reg (pair) |
#define NoCallArgsPassedOnStack 10 |
int NoOfCurFuncArgs; |
int TranslateStackToReg[NoCallArgsPassedOnStack]; |
139,42 → 168,24 |
int ParamLocOnStack[NoCallArgsPassedOnStack]; |
int TotalBytesPushedOnStack; |
/* defined if function parameters must be evaluated in reverse order */ |
#ifndef FALSE |
# define FALSE 0 |
# define TRUE 1 |
#endif |
//#define INVERT_FUNC_PARAMS |
#undef BOOL |
#define BOOL int |
/* defined if structures are passed as pointers. Otherwise structures |
are directly pushed on stack. */ |
//#define FUNC_STRUCT_PARAM_AS_PTR |
#define ALWAYS_ASSERT(x) \ |
do {\ |
if (!(x))\ |
tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\ |
} while (0) |
/* pointer size, in bytes */ |
#define PTR_SIZE 4 |
/* long double size and alignment, in bytes */ |
#define LDOUBLE_SIZE 12 |
#define LDOUBLE_ALIGN 4 |
/* maximum alignment (for aligned attribute support) */ |
#define MAX_ALIGN 8 |
/******************************************************/ |
/* ELF defines */ |
#define EM_TCC_TARGET EM_C60 |
/* relocation type for 32 bit data relocation */ |
#define R_DATA_32 R_C60_32 |
#define R_JMP_SLOT R_C60_JMP_SLOT |
#define R_COPY R_C60_COPY |
#define ELF_START_ADDR 0x00000400 |
#define ELF_PAGE_SIZE 0x1000 |
/******************************************************/ |
static unsigned long func_sub_sp_offset; |
static int func_ret_sub; |
static BOOL C67_invert_test; |
static int C67_compare_reg; |
182,7 → 193,6 |
FILE *f = NULL; |
#endif |
void C67_g(int c) |
{ |
int ind1; |
235,8 → 245,8 |
} |
// these are regs that tcc doesn't really know about, |
// but asign them unique values so the mapping routines |
// can distinquish them |
// but assign them unique values so the mapping routines |
// can distinguish them |
#define C67_A0 105 |
#define C67_SP 106 |
243,7 → 253,7 |
#define C67_B3 107 |
#define C67_FP 108 |
#define C67_B2 109 |
#define C67_CREG_ZERO -1 // Special code for no condition reg test |
#define C67_CREG_ZERO -1 /* Special code for no condition reg test */ |
int ConvertRegToRegClass(int r) |
1552,12 → 1562,12 |
void load(int r, SValue * sv) |
{ |
int v, t, ft, fc, fr, size = 0, element; |
BOOL Unsigned = false; |
BOOL Unsigned = FALSE; |
SValue v1; |
fr = sv->r; |
ft = sv->type.t; |
fc = sv->c.ul; |
fc = sv->c.i; |
v = fr & VT_VALMASK; |
if (fr & VT_LVAL) { |
1564,11 → 1574,11 |
if (v == VT_LLOCAL) { |
v1.type.t = VT_INT; |
v1.r = VT_LOCAL | VT_LVAL; |
v1.c.ul = fc; |
v1.c.i = fc; |
load(r, &v1); |
fr = r; |
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) { |
error("long double not supported"); |
tcc_error("long double not supported"); |
} else if ((ft & VT_TYPE) == VT_BYTE) { |
size = 1; |
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { |
1716,13 → 1726,13 |
int fr, bt, ft, fc, size, t, element; |
ft = v->type.t; |
fc = v->c.ul; |
fc = v->c.i; |
fr = v->r & VT_VALMASK; |
bt = ft & VT_BTYPE; |
/* XXX: incorrect if float reg to reg */ |
if (bt == VT_LDOUBLE) { |
error("long double not supported"); |
tcc_error("long double not supported"); |
} else { |
if (bt == VT_SHORT) |
size = 2; |
1869,6 → 1879,13 |
} |
} |
/* Return the number of registers needed to return the struct, or 0 if |
returning via struct pointer. */ |
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) { |
*ret_align = 1; // Never have to re-align return values for x86-64 |
return 0; |
} |
/* generate function call with address in (vtop->t, vtop->c) and free function |
context. Stack entry is popped */ |
void gfunc_call(int nb_args) |
1877,7 → 1894,7 |
int args_sizes[NoCallArgsPassedOnStack]; |
if (nb_args > NoCallArgsPassedOnStack) { |
error("more than 10 function params not currently supported"); |
tcc_error("more than 10 function params not currently supported"); |
// handle more than 10, put some on the stack |
} |
1884,8 → 1901,6 |
for (i = 0; i < nb_args; i++) { |
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
ALWAYS_ASSERT(FALSE); |
} else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
ALWAYS_ASSERT(FALSE); |
} else { |
/* simple type (currently always same size) */ |
/* XXX: implicit cast ? */ |
1892,9 → 1907,9 |
if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { |
error("long long not supported"); |
tcc_error("long long not supported"); |
} else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { |
error("long double not supported"); |
tcc_error("long double not supported"); |
} else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) { |
size = 8; |
} else { |
1954,6 → 1969,7 |
/* if the function returns a structure, then add an |
implicit pointer parameter */ |
func_vt = sym->type; |
func_var = (sym->c == FUNC_ELLIPSIS); |
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { |
func_vc = addr; |
addr += 4; |
1964,7 → 1980,7 |
/* define parameters */ |
while ((sym = sym->next) != NULL) { |
type = &sym->type; |
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr); |
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr); |
size = type_size(type, &align); |
size = (size + 3) & ~3; |
2090,13 → 2106,12 |
/* && or || optimization */ |
if ((v & 1) == inv) { |
/* insert vtop->c jump list in t */ |
p = &vtop->c.i; |
// I guess the idea is to traverse to the |
// null at the end of the list and store t |
// there |
n = *p; |
n = vtop->c.i; |
while (n != 0) { |
p = (int *) (cur_text_section->data + n); |
2112,38 → 2127,7 |
t = gjmp(t); |
gsym(vtop->c.i); |
} |
} else { |
if (is_float(vtop->type.t)) { |
vpushi(0); |
gen_op(TOK_NE); |
} |
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
/* constant jmp optimization */ |
if ((vtop->c.i != 0) != inv) |
t = gjmp(t); |
} else { |
// I think we need to get the value on the stack |
// into a register, test it, and generate a branch |
// return the address of the branch, so it can be |
// later patched |
v = gv(RC_INT); // get value into a reg |
ind1 = ind; |
C67_MVKL(C67_A0, t); //r=reg to load, constant |
C67_MVKH(C67_A0, t); //r=reg to load, constant |
if (v != TREG_EAX && // check if not already in a conditional test reg |
v != TREG_EDX && v != TREG_ST0 && v != C67_B2) { |
C67_MV(v, C67_B2); |
v = C67_B2; |
} |
C67_IREG_B_REG(inv, v, C67_A0); // [!R] B.S2x A0 |
C67_NOP(5); |
t = ind1; //return where we need to patch |
ind1 = ind; |
} |
} |
vtop--; |
return t; |
} |
2178,34 → 2162,34 |
if (op == TOK_LT) { |
C67_CMPLT(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_GE) { |
C67_CMPLT(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else if (op == TOK_GT) { |
C67_CMPGT(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_LE) { |
C67_CMPGT(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else if (op == TOK_EQ) { |
C67_CMPEQ(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_NE) { |
C67_CMPEQ(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else if (op == TOK_ULT) { |
C67_CMPLTU(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_UGE) { |
C67_CMPLTU(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else if (op == TOK_UGT) { |
C67_CMPGTU(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_ULE) { |
C67_CMPGTU(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else if (op == '+') |
C67_ADD(fr, r); // ADD r,fr,r |
else if (op == '-') |
2319,13 → 2303,13 |
gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side |
ft = vtop->type.t; |
fc = vtop->c.ul; |
fc = vtop->c.i; |
r = vtop->r; |
fr = vtop[-1].r; |
if ((ft & VT_BTYPE) == VT_LDOUBLE) |
error("long doubles not supported"); |
tcc_error("long doubles not supported"); |
if (op >= TOK_ULT && op <= TOK_GT) { |
2340,7 → 2324,7 |
else |
C67_CMPLTSP(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_GE) { |
if ((ft & VT_BTYPE) == VT_DOUBLE) |
C67_CMPLTDP(r, fr, C67_B2); |
2347,7 → 2331,7 |
else |
C67_CMPLTSP(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else if (op == TOK_GT) { |
if ((ft & VT_BTYPE) == VT_DOUBLE) |
C67_CMPGTDP(r, fr, C67_B2); |
2354,7 → 2338,7 |
else |
C67_CMPGTSP(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_LE) { |
if ((ft & VT_BTYPE) == VT_DOUBLE) |
C67_CMPGTDP(r, fr, C67_B2); |
2361,7 → 2345,7 |
else |
C67_CMPGTSP(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else if (op == TOK_EQ) { |
if ((ft & VT_BTYPE) == VT_DOUBLE) |
C67_CMPEQDP(r, fr, C67_B2); |
2368,7 → 2352,7 |
else |
C67_CMPEQSP(r, fr, C67_B2); |
C67_invert_test = false; |
C67_invert_test = FALSE; |
} else if (op == TOK_NE) { |
if ((ft & VT_BTYPE) == VT_DOUBLE) |
C67_CMPEQDP(r, fr, C67_B2); |
2375,7 → 2359,7 |
else |
C67_CMPEQSP(r, fr, C67_B2); |
C67_invert_test = true; |
C67_invert_test = TRUE; |
} else { |
ALWAYS_ASSERT(FALSE); |
} |
2477,7 → 2461,7 |
r = vtop->r; |
if (t != VT_INT) |
error("long long not supported"); |
tcc_error("long long not supported"); |
else { |
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) { |
C67_DPTRUNC(r, r); |
2544,5 → 2528,22 |
vtop--; |
} |
/* end of X86 code generator */ |
/* Save the stack pointer onto the stack and return the location of its address */ |
ST_FUNC void gen_vla_sp_save(int addr) { |
tcc_error("variable length arrays unsupported for this target"); |
} |
/* Restore the SP from a location on the stack */ |
ST_FUNC void gen_vla_sp_restore(int addr) { |
tcc_error("variable length arrays unsupported for this target"); |
} |
/* Subtract from the stack pointer, and push the resulting value onto the stack */ |
ST_FUNC void gen_vla_alloc(CType *type, int align) { |
tcc_error("variable length arrays unsupported for this target"); |
} |
/* end of C67 code generator */ |
/*************************************************************/ |
#endif |
/*************************************************************/ |
/programs/develop/ktcc/trunk/source/coff.h |
---|
37,8 → 37,8 |
#define F_BYTE_ORDER (F_LITTLE | F_BIG) |
#define FILHDR struct filehdr |
//#define FILHSZ sizeof(FILHDR) |
#define FILHSZ 22 // above rounds to align on 4 bytes which causes problems |
/* #define FILHSZ sizeof(FILHDR) */ |
#define FILHSZ 22 /* above rounds to align on 4 bytes which causes problems */ |
#define COFF_C67_MAGIC 0x00c2 |
150,7 → 150,7 |
/*------------------------------------------------------------------------*/ |
/* Define constants for names of "special" sections */ |
/*------------------------------------------------------------------------*/ |
//#define _TEXT ".text" |
/* #define _TEXT ".text" */ |
#define _DATA ".data" |
#define _BSS ".bss" |
#define _CINIT ".cinit" |
/programs/develop/ktcc/trunk/source/config.h |
---|
1,11 → 1,8 |
/* Automatically generated by configure - do not modify */ |
#define CONFIG_TCCDIR "/usr/local/lib/tcc" |
#define GCC_MAJOR 3 |
#define HOST_I386 1 |
#define TCC_VERSION "0.9.23" |
//#define TCC_TARGET_PE |
#define TCC_VERSION "0.9.26" |
#define CONFIG_TCC_STATIC |
#define TCC_TARGET_MEOS |
#define TCC_TARGET_I386 |
#define ONE_SOURCE |
/* enable bound checking code */ |
//#define CONFIG_TCC_BCHECK 1 |
#define COMMIT_4ad186c5ef61_IS_FIXED |
/programs/develop/ktcc/trunk/source/config.h.in |
---|
0,0 → 1,7 |
#define CONFIG_TCCDIR "${CONFIG_TCCDIR}" |
#define TCC_VERSION "${TCC_VERSION}" |
#cmakedefine CONFIG_WIN32 |
#cmakedefine CONFIG_WIN64 |
#cmakedefine CONFIG_TCC_BCHECK |
#cmakedefine CONFIG_TCC_ASSERT |
/programs/develop/ktcc/trunk/source/config.h_meos |
---|
0,0 → 1,8 |
#define TCC_VERSION "0.9.26" |
#define CONFIG_TCC_STATIC |
#define TCC_TARGET_MEOS |
#define TCC_TARGET_I386 |
#define ONE_SOURCE |
#define COMMIT_4ad186c5ef61_IS_FIXED |
/programs/develop/ktcc/trunk/source/config.texi.in |
---|
0,0 → 1,0 |
@set VERSION ${TCC_VERSION} |
/programs/develop/ktcc/trunk/source/configure |
---|
0,0 → 1,613 |
#!/bin/sh |
# |
# tcc configure script (c) 2003 Fabrice Bellard |
# set temporary file name |
# if test ! -z "$TMPDIR" ; then |
# TMPDIR1="${TMPDIR}" |
# elif test ! -z "$TEMPDIR" ; then |
# TMPDIR1="${TEMPDIR}" |
# else |
# TMPDIR1="/tmp" |
# fi |
# |
# bashism: TMPN="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c" |
TMPN="./conftest-$$" |
TMPH=$TMPN.h |
# default parameters |
build_cross="no" |
use_libgcc="no" |
enable_assert="no" |
prefix="" |
execprefix="" |
bindir="" |
libdir="" |
tccdir="" |
includedir="" |
mandir="" |
infodir="" |
sysroot="" |
cross_prefix="" |
cc="gcc" |
host_cc="gcc" |
ar="ar" |
strip="strip" |
cygwin="no" |
gprof="no" |
bigendian="no" |
mingw32="no" |
LIBSUF=".a" |
EXESUF="" |
tcc_sysincludepaths="" |
tcc_libpaths="" |
tcc_crtprefix="" |
tcc_elfinterp="" |
tcc_lddir= |
confvars= |
cpu= |
host_os=`uname` |
case $host_os in |
MINGW32*) host_os=Windows; ;; |
*) ;; |
esac |
# OS specific |
targetos=`uname` |
case $targetos in |
MINGW32*) mingw32=yes; host_os=Windows; ;; |
DragonFly) noldl=yes;; |
OpenBSD) noldl=yes;; |
FreeBSD) noldl=yes;; |
NetBSD) noldl=yes;; |
*) ;; |
esac |
# find source path |
# XXX: we assume an absolute path is given when launching configure, |
# except in './configure' case. |
source_path=${0%configure} |
source_path=${source_path%/} |
source_path_used="yes" |
if test -z "$source_path" -o "$source_path" = "." ; then |
source_path=`pwd` |
source_path_used="no" |
fi |
classify_cpu () |
{ |
cpu="$1" |
case "$cpu" in |
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386) |
cpu="x86" |
;; |
x86_64|amd64) |
cpu="x86-64" |
;; |
arm*) |
case "$cpu" in |
arm|armv4l) |
cpuver=4 |
;; |
armv5tel|armv5tejl) |
cpuver=5 |
;; |
armv6j|armv6l) |
cpuver=6 |
;; |
armv7a|armv7l) |
cpuver=7 |
;; |
esac |
cpu="armv4l" |
;; |
aarch64) |
cpu="aarch64" |
;; |
alpha) |
cpu="alpha" |
;; |
"Power Macintosh"|ppc|ppc64) |
cpu="powerpc" |
;; |
mips) |
cpu="mips" |
;; |
s390) |
cpu="s390" |
;; |
*) |
echo "Unsupported CPU: $cpu" |
exit 1 |
;; |
esac |
} |
for opt do |
eval opt=\"$opt\" |
case "$opt" in |
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2` |
;; |
--exec-prefix=*) execprefix=`echo $opt | cut -d '=' -f 2` |
;; |
--tccdir=*) tccdir=`echo $opt | cut -d '=' -f 2` |
;; |
--bindir=*) bindir=`echo $opt | cut -d '=' -f 2` |
;; |
--libdir=*) libdir=`echo $opt | cut -d '=' -f 2` |
;; |
--includedir=*) includedir=`echo $opt | cut -d '=' -f 2` |
;; |
--sharedir=*) sharedir=`echo $opt | cut -d '=' -f 2` |
;; |
--mandir=*) mandir=`echo $opt | cut -d '=' -f 2` |
;; |
--infodir=*) infodir=`echo $opt | cut -d '=' -f 2` |
;; |
--docdir=*) docdir=`echo $opt | cut -d '=' -f 2` |
;; |
--sysroot=*) sysroot=`echo $opt | cut -d '=' -f 2` |
;; |
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2` |
;; |
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2` |
;; |
--sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2` |
;; |
--libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2` |
;; |
--crtprefix=*) tcc_crtprefix=`echo $opt | cut -d '=' -f 2` |
;; |
--elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2` |
;; |
--cc=*) cc=`echo $opt | cut -d '=' -f 2` |
;; |
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}" |
;; |
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}" |
;; |
--extra-libs=*) extralibs=${opt#--extra-libs=} |
;; |
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2` |
;; |
--enable-gprof) gprof="yes" |
;; |
--enable-mingw32) mingw32="yes" ; cross_prefix="i686-pc-mingw32-" ; cpu=x86; targetos=Windows; |
;; |
--enable-cygwin) mingw32="yes" ; cygwin="yes" ; cross_prefix="mingw32-" ; cpu=x86; targetos=Windows; |
;; |
--enable-tcc32-mingw) mingw32="yes" ; cross_prefix="i386-win-" ; cpu=x86; cc=tcc; targetos=Windows; |
;; |
--enable-tcc64-mingw) mingw32="yes" ; cross_prefix="x86_64-win-" ; cpu=x86_64; cc=tcc; targetos=Windows; |
;; |
--enable-cross) build_cross="yes" |
;; |
--enable-assert) enable_assert="yes" |
;; |
--disable-static) disable_static="yes" |
;; |
--disable-rpath) disable_rpath="yes" |
;; |
--strip-binaries) strip_binaries="yes" |
;; |
--with-libgcc) use_libgcc="yes" |
;; |
--with-selinux) have_selinux="yes" |
;; |
--help|-h) show_help="yes" |
;; |
*) echo "configure: WARNING: unrecognized option $opt" |
;; |
esac |
done |
if test -z "$cpu" ; then |
if test -n "$ARCH" ; then |
cpu="$ARCH" |
else |
cpu=`uname -m` |
fi |
fi |
classify_cpu "$cpu" |
# Checking for CFLAGS |
if test -z "$CFLAGS"; then |
CFLAGS="-Wall -g -O0" |
fi |
if test "$mingw32" = "yes" ; then |
if test x"$tccdir" = x""; then |
tccdir="tcc" |
fi |
if test -z "$prefix" ; then |
prefix="C:/Program Files/${tccdir}" |
fi |
if test -z "$sharedir" ; then |
sharedir="${prefix}" |
fi |
execprefix="$prefix" |
bindir="${prefix}" |
tccdir="${prefix}" |
libdir="${prefix}/lib" |
docdir="${sharedir}/doc" |
mandir="${sharedir}/man" |
infodir="${sharedir}/info" |
LIBSUF=".lib" |
EXESUF=".exe" |
else |
if test -z "$prefix" ; then |
prefix="/usr/local" |
fi |
if test -z "$sharedir" ; then |
sharedir="${prefix}/share" |
fi |
if test x"$execprefix" = x""; then |
execprefix="${prefix}" |
fi |
if test x"$tccdir" = x""; then |
tccdir="tcc" |
fi |
if test x"$libdir" = x""; then |
libdir="${execprefix}/lib" |
if test -n "${tccdir}"; then |
tccdir="${libdir}/${tccdir}" |
else |
tccdir="${libdir}" |
fi |
if test "$cpu" = "x86-64"; then |
libdir="${execprefix}/lib64" |
fi |
else |
tccdir="${libdir}/${tccdir}" |
fi |
if test x"$bindir" = x""; then |
bindir="${execprefix}/bin" |
fi |
if test x"$docdir" = x""; then |
docdir="${sharedir}/doc/${tccdir}" |
fi |
if test x"$mandir" = x""; then |
mandir="${sharedir}/man" |
fi |
if test x"$infodir" = x""; then |
infodir="${sharedir}/info" |
fi |
fi # mingw32 |
if test x"$includedir" = x""; then |
includedir="${prefix}/include" |
fi |
if test x"$show_help" = "xyes" ; then |
cat << EOF |
Usage: configure [options] |
Options: [defaults in brackets after descriptions] |
Standard options: |
--help print this message |
--prefix=PREFIX install in PREFIX [$prefix] |
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX |
[same as prefix] |
--bindir=DIR user executables in DIR [EPREFIX/bin] |
--libdir=DIR object code libraries in DIR [EPREFIX/lib] |
--tccdir=DIR installation directory [EPREFIX/lib/tcc] |
--includedir=DIR C header files in DIR [PREFIX/include] |
--sharedir=DIR documentation root DIR [PREFIX/share] |
--docdir=DIR documentation in DIR [SHAREDIR/doc/tcc] |
--mandir=DIR man documentation in DIR [SHAREDIR/man] |
--infodir=DIR info documentation in DIR [SHAREDIR/info] |
Advanced options (experts only): |
--source-path=PATH path of source code [$source_path] |
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix] |
--sysroot=PREFIX prepend PREFIX to library/include paths [] |
--cc=CC use C compiler CC [$cc] |
--extra-cflags= specify compiler flags [$CFLAGS] |
--extra-ldflags= specify linker options [] |
--cpu=CPU CPU [$cpu] |
--strip-binaries strip symbol tables from resulting binaries |
--disable-static make libtcc.so instead of libtcc.a |
--disable-rpath disable use of -rpath with the above |
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a in dynamic link |
--enable-tcc64-mingw build windows version on linux with x86_64-win-tcc |
--enable-tcc32-mingw build windows version on linux with i386-win-tcc |
--enable-mingw32 build windows version on linux with mingw32 |
--enable-cygwin build windows version on windows with cygwin |
--enable-cross build cross compilers |
--enable-assert enable debug assertions |
--with-selinux use mmap for exec mem [needs writable /tmp] |
--sysincludepaths=... specify system include paths, colon separated |
--libpaths=... specify system library paths, colon separated |
--crtprefix=... specify locations of crt?.o, colon separated |
--elfinterp=... specify elf interpreter |
EOF |
#echo "NOTE: The object files are build at the place where configure is launched" |
exit 1 |
fi |
if test "$cc" != "tcc"; then |
ar="${cross_prefix}${ar}" |
fi |
cc="${cross_prefix}${cc}" |
strip="${cross_prefix}${strip}" |
CONFTEST=./conftest$EXESUF |
if test -z "$cross_prefix" ; then |
if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then |
echo "configure: error: '$cc' failed to compile conftest.c." |
else |
bigendian="$($CONFTEST bigendian)" |
gcc_major="$($CONFTEST version)" |
gcc_minor="$($CONFTEST minor)" |
if test "$mingw32" = "no" ; then |
triplet="$($CONFTEST triplet)" |
if test -f "/usr/lib/$triplet/crti.o" ; then |
tcc_lddir="lib" |
multiarch_triplet="$triplet" |
elif test "$cpu" != "x86" -a -f "/usr/lib64/crti.o" ; then |
tcc_lddir="lib64" |
fi |
if test "$cpu" = "armv4l" ; then |
if test "${triplet%eabihf}" != "$triplet" ; then |
confvars="$confvars arm_eabihf" |
elif test "${triplet%eabi}" != "$triplet" ; then |
confvars="$confvars arm_eabi" |
fi |
if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then |
confvars="$confvars arm_vfp" |
fi |
fi |
# multiarch_triplet=${libc_dir#*/} |
# multiarch_triplet=${multiarch_triplet%/} |
# tcc_lddir="${libc_dir%%/*}" |
# if test -n "$multiarch_triplet" ; then |
# tcc_lddir="$tcc_lddir/$multiarch_triplet" |
# fi |
if test -f "/lib/ld-uClibc.so.0" ; then |
confvars="$confvars uClibc" |
fi |
# gr: maybe for after the release: |
# tcc_elfinterp="$(ldd $CONFTEST | grep 'ld.*.so' | sed 's,\s*\(\S\+\).*,\1,')" |
# echo "elfinterp $tcc_elfinterp" |
fi |
fi |
else |
# if cross compiling, cannot launch a program, so make a static guess |
case $cpu in |
powerpc|mips|s390) bigendian=yes;; |
esac |
fi |
# a final configuration tuning |
W_OPTIONS="declaration-after-statement" |
for i in $W_OPTIONS; do |
O_PRESENT="$($cc -v --help 2>&1 | grep -- -W$i)" |
if test -n "$O_PRESENT"; then CFLAGS="$CFLAGS -W$i"; fi |
done |
W_OPTIONS="deprecated-declarations strict-aliasing pointer-sign sign-compare unused-result uninitialized" |
for i in $W_OPTIONS; do |
O_PRESENT="$($cc -v --help 2>&1 | grep -- -W$i)" |
if test -n "$O_PRESENT"; then CFLAGS="$CFLAGS -Wno-$i"; fi |
done |
F_OPTIONS="strict-aliasing" |
for i in $F_OPTIONS; do |
O_PRESENT="$($cc -v --help 2>&1 | grep -- -f$i)" |
if test -n "$O_PRESENT"; then CFLAGS="$CFLAGS -fno-$i"; fi |
done |
if test -z "$tcc_lddir" -a "$cpu" = "x86-64"; then tcc_lddir="lib64"; fi |
echo "Binary directory $bindir" |
echo "TinyCC directory $tccdir" |
echo "Library directory $libdir" |
echo "Include directory $includedir" |
echo "Manual directory $mandir" |
echo "Info directory $infodir" |
echo "Doc directory $docdir" |
echo "Target root prefix $sysroot" |
echo "Source path $source_path" |
echo "C compiler $cc" |
echo "cross compilers $build_cross" |
if test "$build_cross" = "no"; then |
echo "Target CPU $cpu" |
fi |
echo "Host OS $host_os" |
echo "Target OS $targetos" |
echo "Big Endian $bigendian" |
echo "gprof enabled $gprof" |
echo "use libgcc $use_libgcc" |
echo "Creating config.mak and config.h" |
cat >config.mak <<EOF |
# Automatically generated by configure - do not modify |
prefix=$prefix |
bindir=\$(DESTDIR)$bindir |
tccdir=\$(DESTDIR)$tccdir |
libdir=\$(DESTDIR)$libdir |
ln_libdir=$libdir |
includedir=\$(DESTDIR)$includedir |
mandir=\$(DESTDIR)$mandir |
infodir=\$(DESTDIR)$infodir |
docdir=\$(DESTDIR)$docdir |
CC=$cc |
GCC_MAJOR=$gcc_major |
GCC_MINOR=$gcc_minor |
HOST_CC=$host_cc |
AR=$ar |
STRIP=$strip -s -R .comment -R .note |
CFLAGS=$CFLAGS |
LDFLAGS=$LDFLAGS |
LIBSUF=$LIBSUF |
EXESUF=$EXESUF |
HOST_OS=$host_os |
EOF |
if test "$mingw32" = "yes" -a "$host_os" != "Windows" ; then |
cat >>config.mak <<EOF |
XCC=$cc |
XAR=$ar |
EOF |
fi |
print_inc() { |
if test -n "$2"; then |
echo "#ifndef $1" >> $TMPH |
echo "# define $1 \"$2\"" >> $TMPH |
echo "#endif" >> $TMPH |
fi |
} |
print_mak() { |
if test -n "$2"; then |
echo "NATIVE_DEFINES+=-D$1=\"\\\"$2\\\"\"" >> config.mak |
fi |
} |
echo "/* Automatically generated by configure - do not modify */" > $TMPH |
print_inc CONFIG_SYSROOT "$sysroot" |
print_inc CONFIG_TCCDIR "$tccdir" |
if test "$build_cross" = "no"; then |
print_inc CONFIG_LDDIR "$tcc_lddir" |
fi |
print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths" |
print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths" |
print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix" |
print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp" |
print_mak CONFIG_MULTIARCHDIR "$multiarch_triplet" |
echo "#define GCC_MAJOR $gcc_major" >> $TMPH |
echo "#define GCC_MINOR $gcc_minor" >> $TMPH |
if test "$cpu" = "x86" ; then |
echo "ARCH=i386" >> config.mak |
elif test "$cpu" = "x86-64" ; then |
echo "ARCH=x86-64" >> config.mak |
elif test "$cpu" = "armv4l" ; then |
echo "ARCH=arm" >> config.mak |
echo "#define TCC_ARM_VERSION $cpuver" >> $TMPH |
elif test "$cpu" = "aarch64" ; then |
echo "ARCH=arm64" >> config.mak |
elif test "$cpu" = "powerpc" ; then |
echo "ARCH=ppc" >> config.mak |
elif test "$cpu" = "mips" ; then |
echo "ARCH=mips" >> config.mak |
elif test "$cpu" = "s390" ; then |
echo "ARCH=s390" >> config.mak |
elif test "$cpu" = "alpha" ; then |
echo "ARCH=alpha" >> config.mak |
else |
echo "Unsupported CPU" |
exit 1 |
fi |
echo "TARGETOS=$targetos" >> config.mak |
for v in $confvars ; do |
echo "CONFIG_$v=yes" >> config.mak |
done |
if test "$noldl" = "yes" ; then |
echo "CONFIG_NOLDL=yes" >> config.mak |
fi |
if test "$mingw32" = "yes" ; then |
echo "CONFIG_WIN32=yes" >> config.mak |
echo "#define CONFIG_WIN32 1" >> $TMPH |
fi |
if test "$cygwin" = "yes" ; then |
echo "#ifndef _WIN32" >> $TMPH |
echo "# define _WIN32" >> $TMPH |
echo "#endif" >> $TMPH |
echo "AR=ar" >> config.mak |
fi |
if test "$bigendian" = "yes" ; then |
echo "WORDS_BIGENDIAN=yes" >> config.mak |
echo "#define WORDS_BIGENDIAN 1" >> $TMPH |
fi |
if test "$gprof" = "yes" ; then |
echo "TARGET_GPROF=yes" >> config.mak |
echo "#define HAVE_GPROF 1" >> $TMPH |
fi |
if test "$build_cross" = "yes" ; then |
echo "CONFIG_CROSS=yes" >> config.mak |
fi |
if test "$disable_static" = "yes" ; then |
echo "DISABLE_STATIC=yes" >> config.mak |
fi |
if test "$disable_rpath" = "yes" ; then |
echo "DISABLE_RPATH=yes" >> config.mak |
fi |
if test "$strip_binaries" = "yes" ; then |
echo "STRIP_BINARIES=yes" >> config.mak |
fi |
if test "$use_libgcc" = "yes" ; then |
echo "#define CONFIG_USE_LIBGCC" >> $TMPH |
echo "CONFIG_USE_LIBGCC=yes" >> config.mak |
fi |
if test "$have_selinux" = "yes" ; then |
echo "#define HAVE_SELINUX" >> $TMPH |
echo "HAVE_SELINUX=yes" >> config.mak |
fi |
if test "$enable_assert" = "yes" ; then |
echo "#define CONFIG_TCC_ASSERT" >> $TMPH |
fi |
version=`head $source_path/VERSION` |
echo "VERSION=$version" >>config.mak |
echo "#define TCC_VERSION \"$version\"" >> $TMPH |
echo "@set VERSION $version" > config.texi |
echo "SRC_PATH=$source_path" >>config.mak |
if test "$source_path_used" = "yes" ; then |
case $source_path in |
/*) echo "top_srcdir=$source_path";; |
*) echo "top_srcdir=\$(TOP)/$source_path";; |
esac >>config.mak |
else |
echo 'top_srcdir=$(TOP)' >>config.mak |
fi |
echo 'top_builddir=$(TOP)' >>config.mak |
diff $TMPH config.h >/dev/null 2>&1 |
if test $? -ne 0 ; then |
mv -f $TMPH config.h |
else |
echo "config.h is unchanged" |
fi |
rm -f $TMPN* $CONFTEST |
# --------------------------------------------------------------------------- |
# build tree in object directory if source path is different from current one |
fn_makelink() |
{ |
tgt=$1/$2 |
case $2 in |
*/*) dn=${2%/*} |
test -d $dn || mkdir -p $dn |
case $1 in |
/*) ;; |
*) while test $dn ; do |
tgt=../$tgt; dn=${dn#${dn%%/*}}; dn=${dn#/} |
done |
;; |
esac |
;; |
esac |
ln -sfn $tgt $2 |
} |
if test "$source_path_used" = "yes" ; then |
FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile" |
for f in $FILES ; do |
fn_makelink $source_path $f |
done |
fi |
# --------------------------------------------------------------------------- |
/programs/develop/ktcc/trunk/source/conftest.c |
---|
0,0 → 1,77 |
#include <stdio.h> |
/* Define architecture */ |
#if defined(__i386__) |
# define TRIPLET_ARCH "i386" |
#elif defined(__x86_64__) |
# define TRIPLET_ARCH "x86_64" |
#elif defined(__arm__) |
# define TRIPLET_ARCH "arm" |
#elif defined(__aarch64__) |
# define TRIPLET_ARCH "aarch64" |
#else |
# define TRIPLET_ARCH "unknown" |
#endif |
/* Define OS */ |
#if defined (__linux__) |
# define TRIPLET_OS "linux" |
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) |
# define TRIPLET_OS "kfreebsd" |
#elif !defined (__GNU__) |
# define TRIPLET_OS "unknown" |
#endif |
/* Define calling convention and ABI */ |
#if defined (__ARM_EABI__) |
# if defined (__ARM_PCS_VFP) |
# define TRIPLET_ABI "gnueabihf" |
# else |
# define TRIPLET_ABI "gnueabi" |
# endif |
#else |
# define TRIPLET_ABI "gnu" |
#endif |
#ifdef __GNU__ |
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI |
#else |
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI |
#endif |
#if defined(_WIN32) |
int _CRT_glob = 0; |
#endif |
int main(int argc, char *argv[]) |
{ |
switch(argc == 2 ? argv[1][0] : 0) { |
case 'b': |
{ |
volatile unsigned foo = 0x01234567; |
puts(*(unsigned char*)&foo == 0x67 ? "no" : "yes"); |
break; |
} |
#ifdef __GNUC__ |
case 'm': |
printf("%d\n", __GNUC_MINOR__); |
break; |
case 'v': |
printf("%d\n", __GNUC__); |
break; |
#else |
case 'm': |
case 'v': |
puts("0"); |
break; |
#endif |
case 't': |
puts(TRIPLET); |
break; |
case -1: |
/* to test -Wno-unused-result */ |
fread(NULL, 1, 1, NULL); |
break; |
} |
return 0; |
} |
/programs/develop/ktcc/trunk/source/elf.h |
---|
1,27 → 1,25 |
/* This file defines standard ELF types, structures, and macros. |
Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. |
Copyright (C) 1995-2012 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Ian Lance Taylor <ian@cygnus.com>. |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public License as |
published by the Free Software Foundation; either version 2 of the |
License, or (at your option) any later version. |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
The GNU C Library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
Lesser General Public License for more details. |
You should have received a copy of the GNU Library General Public |
License along with the GNU C Library; see the file COPYING.LIB. If not, |
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
Boston, MA 02111-1307, USA. */ |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, see |
<http://www.gnu.org/licenses/>. */ |
#ifndef _ELF_H |
#define _ELF_H 1 |
#ifndef WIN32 |
#ifndef _WIN32 |
#include <inttypes.h> |
#else |
#ifndef __int8_t_defined |
68,9 → 66,9 |
typedef uint16_t Elf32_Section; |
typedef uint16_t Elf64_Section; |
/* Type of symbol indices. */ |
typedef uint32_t Elf32_Symndx; |
typedef uint64_t Elf64_Symndx; |
/* Type for version symbol information. */ |
typedef Elf32_Half Elf32_Versym; |
typedef Elf64_Half Elf64_Versym; |
/* The ELF file header. This appears at the start of every ELF file. */ |
149,9 → 147,20 |
/* Value must be EV_CURRENT */ |
#define EI_OSABI 7 /* OS ABI identification */ |
#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ |
#define ELFOSABI_NONE 0 /* UNIX System V ABI */ |
#define ELFOSABI_SYSV 0 /* Alias. */ |
#define ELFOSABI_HPUX 1 /* HP-UX */ |
#define ELFOSABI_FREEBSD 9 /* Free BSD */ |
#define ELFOSABI_NETBSD 2 /* NetBSD. */ |
#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ |
#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ |
#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ |
#define ELFOSABI_AIX 7 /* IBM AIX. */ |
#define ELFOSABI_IRIX 8 /* SGI Irix. */ |
#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ |
#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ |
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ |
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ |
#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ |
#define ELFOSABI_ARM 97 /* ARM */ |
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ |
167,8 → 176,10 |
#define ET_DYN 3 /* Shared object file */ |
#define ET_CORE 4 /* Core file */ |
#define ET_NUM 5 /* Number of defined types */ |
#define ET_LOPROC 0xff00 /* Processor-specific */ |
#define ET_HIPROC 0xffff /* Processor-specific */ |
#define ET_LOOS 0xfe00 /* OS-specific range start */ |
#define ET_HIOS 0xfeff /* OS-specific range end */ |
#define ET_LOPROC 0xff00 /* Processor-specific range start */ |
#define ET_HIPROC 0xffff /* Processor-specific range end */ |
/* Legal values for e_machine (architecture). */ |
178,24 → 189,23 |
#define EM_386 3 /* Intel 80386 */ |
#define EM_68K 4 /* Motorola m68k family */ |
#define EM_88K 5 /* Motorola m88k family */ |
#define EM_486 6 /* Intel 80486 */ |
#define EM_860 7 /* Intel 80860 */ |
#define EM_MIPS 8 /* MIPS R3000 big-endian */ |
#define EM_S370 9 /* Amdahl */ |
#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ |
#define EM_RS6000 11 /* RS6000 */ |
#define EM_S370 9 /* IBM System/370 */ |
#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ |
#define EM_PARISC 15 /* HPPA */ |
#define EM_nCUBE 16 /* nCUBE */ |
#define EM_VPP500 17 /* Fujitsu VPP500 */ |
#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ |
#define EM_960 19 /* Intel 80960 */ |
#define EM_PPC 20 /* PowerPC */ |
#define EM_PPC64 21 /* PowerPC 64-bit */ |
#define EM_S390 22 /* IBM S390 */ |
#define EM_V800 36 /* NEC V800 series */ |
#define EM_FR20 37 /* Fujitsu FR20 */ |
#define EM_RH32 38 /* TRW RH32 */ |
#define EM_MMA 39 /* Fujitsu MMA */ |
#define EM_RH32 38 /* TRW RH-32 */ |
#define EM_RCE 39 /* Motorola RCE */ |
#define EM_ARM 40 /* ARM */ |
#define EM_FAKE_ALPHA 41 /* Digital Alpha */ |
#define EM_SH 42 /* Hitachi SH */ |
210,8 → 220,51 |
#define EM_MIPS_X 51 /* Stanford MIPS-X */ |
#define EM_COLDFIRE 52 /* Motorola Coldfire */ |
#define EM_68HC12 53 /* Motorola M68HC12 */ |
#define EM_NUM 54 |
#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ |
#define EM_PCP 55 /* Siemens PCP */ |
#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ |
#define EM_NDR1 57 /* Denso NDR1 microprocessor */ |
#define EM_STARCORE 58 /* Motorola Start*Core processor */ |
#define EM_ME16 59 /* Toyota ME16 processor */ |
#define EM_ST100 60 /* STMicroelectronic ST100 processor */ |
#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ |
#define EM_X86_64 62 /* AMD x86-64 architecture */ |
#define EM_PDSP 63 /* Sony DSP Processor */ |
#define EM_FX66 66 /* Siemens FX66 microcontroller */ |
#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ |
#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ |
#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ |
#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ |
#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ |
#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ |
#define EM_SVX 73 /* Silicon Graphics SVx */ |
#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ |
#define EM_VAX 75 /* Digital VAX */ |
#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ |
#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ |
#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ |
#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ |
#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ |
#define EM_HUANY 81 /* Harvard University machine-independent object files */ |
#define EM_PRISM 82 /* SiTera Prism */ |
#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ |
#define EM_FR30 84 /* Fujitsu FR30 */ |
#define EM_D10V 85 /* Mitsubishi D10V */ |
#define EM_D30V 86 /* Mitsubishi D30V */ |
#define EM_V850 87 /* NEC v850 */ |
#define EM_M32R 88 /* Mitsubishi M32R */ |
#define EM_MN10300 89 /* Matsushita MN10300 */ |
#define EM_MN10200 90 /* Matsushita MN10200 */ |
#define EM_PJ 91 /* picoJava */ |
#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ |
#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ |
#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ |
#define EM_AARCH64 183 /* ARM AARCH64 */ |
#define EM_TILEPRO 188 /* Tilera TILEPro */ |
#define EM_TILEGX 191 /* Tilera TILE-Gx */ |
#define EM_NUM 192 |
/* If it is necessary to assign new unofficial EM_* values, please |
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the |
chances of collision with official or non-GNU unofficial values. */ |
260,9 → 313,16 |
#define SHN_UNDEF 0 /* Undefined section */ |
#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ |
#define SHN_LOPROC 0xff00 /* Start of processor-specific */ |
#define SHN_BEFORE 0xff00 /* Order section before all others |
(Solaris). */ |
#define SHN_AFTER 0xff01 /* Order section after all others |
(Solaris). */ |
#define SHN_HIPROC 0xff1f /* End of processor-specific */ |
#define SHN_LOOS 0xff20 /* Start of OS-specific */ |
#define SHN_HIOS 0xff3f /* End of OS-specific */ |
#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ |
#define SHN_COMMON 0xfff2 /* Associated symbol is common */ |
#define SHN_XINDEX 0xffff /* Index is in extra table. */ |
#define SHN_HIRESERVE 0xffff /* End of reserved indices */ |
/* Legal values for sh_type (section type). */ |
279,9 → 339,19 |
#define SHT_REL 9 /* Relocation entries, no addends */ |
#define SHT_SHLIB 10 /* Reserved */ |
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ |
#define SHT_NUM 12 /* Number of defined types. */ |
#define SHT_LOOS 0x60000000 /* Start OS-specific */ |
#define SHT_LOSUNW 0x6ffffffb /* Sun-specific low bound. */ |
#define SHT_INIT_ARRAY 14 /* Array of constructors */ |
#define SHT_FINI_ARRAY 15 /* Array of destructors */ |
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ |
#define SHT_GROUP 17 /* Section group */ |
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ |
#define SHT_NUM 19 /* Number of defined types. */ |
#define SHT_LOOS 0x60000000 /* Start OS-specific. */ |
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ |
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ |
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ |
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ |
#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ |
#define SHT_SUNW_move 0x6ffffffa |
#define SHT_SUNW_COMDAT 0x6ffffffb |
#define SHT_SUNW_syminfo 0x6ffffffc |
#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ |
299,8 → 369,24 |
#define SHF_WRITE (1 << 0) /* Writable */ |
#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ |
#define SHF_EXECINSTR (1 << 2) /* Executable */ |
#define SHF_MERGE (1 << 4) /* Might be merged */ |
#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ |
#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ |
#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ |
#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling |
required */ |
#define SHF_GROUP (1 << 9) /* Section is member of a group. */ |
#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ |
#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ |
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ |
#define SHF_ORDERED (1 << 30) /* Special ordering requirement |
(Solaris). */ |
#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless |
referenced or allocated (Solaris).*/ |
/* Section group handling. */ |
#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ |
/* Symbol table entry. */ |
typedef struct |
309,7 → 395,7 |
Elf32_Addr st_value; /* Symbol value */ |
Elf32_Word st_size; /* Symbol size */ |
unsigned char st_info; /* Symbol type and binding */ |
unsigned char st_other; /* No defined meaning, 0 */ |
unsigned char st_other; /* Symbol visibility */ |
Elf32_Section st_shndx; /* Section index */ |
} Elf32_Sym; |
317,7 → 403,7 |
{ |
Elf64_Word st_name; /* Symbol name (string tbl index) */ |
unsigned char st_info; /* Symbol type and binding */ |
unsigned char st_other; /* No defined meaning, 0 */ |
unsigned char st_other; /* Symbol visibility */ |
Elf64_Section st_shndx; /* Section index */ |
Elf64_Addr st_value; /* Symbol value */ |
Elf64_Xword st_size; /* Symbol size */ |
355,10 → 441,6 |
#define SYMINFO_NUM 2 |
/* Special section index. */ |
#define SHN_UNDEF 0 /* No section, undefined symbol. */ |
/* How to extract and insert information held in the st_info field. */ |
#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) |
377,6 → 459,7 |
#define STB_WEAK 2 /* Weak symbol */ |
#define STB_NUM 3 /* Number of defined types. */ |
#define STB_LOOS 10 /* Start of OS-specific */ |
#define STB_GNU_UNIQUE 10 /* Unique symbol. */ |
#define STB_HIOS 12 /* End of OS-specific */ |
#define STB_LOPROC 13 /* Start of processor-specific */ |
#define STB_HIPROC 15 /* End of processor-specific */ |
388,8 → 471,11 |
#define STT_FUNC 2 /* Symbol is a code object */ |
#define STT_SECTION 3 /* Symbol associated with a section */ |
#define STT_FILE 4 /* Symbol's name is file name */ |
#define STT_NUM 5 /* Number of defined types. */ |
#define STT_LOOS 11 /* Start of OS-specific */ |
#define STT_COMMON 5 /* Symbol is a common data object */ |
#define STT_TLS 6 /* Symbol is thread-local data object*/ |
#define STT_NUM 7 /* Number of defined types. */ |
#define STT_LOOS 10 /* Start of OS-specific */ |
#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ |
#define STT_HIOS 12 /* End of OS-specific */ |
#define STT_LOPROC 13 /* Start of processor-specific */ |
#define STT_HIPROC 15 /* End of processor-specific */ |
459,7 → 545,7 |
#define ELF64_R_SYM(i) ((i) >> 32) |
#define ELF64_R_TYPE(i) ((i) & 0xffffffff) |
#define ELF64_R_INFO(sym,type) (((sym) << 32) + (type)) |
#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) |
/* Program segment header. */ |
487,6 → 573,12 |
Elf64_Xword p_align; /* Segment alignment */ |
} Elf64_Phdr; |
/* Special value for e_phnum. This indicates that the real number of |
program headers is too large to fit into e_phnum. Instead the real |
value is in the field sh_info of section 0. */ |
#define PN_XNUM 0xffff |
/* Legal values for p_type (segment type). */ |
#define PT_NULL 0 /* Program header table entry unused */ |
496,8 → 588,16 |
#define PT_NOTE 4 /* Auxiliary information */ |
#define PT_SHLIB 5 /* Reserved */ |
#define PT_PHDR 6 /* Entry for header table itself */ |
#define PT_NUM 7 /* Number of defined types. */ |
#define PT_TLS 7 /* Thread-local storage segment */ |
#define PT_NUM 8 /* Number of defined types */ |
#define PT_LOOS 0x60000000 /* Start of OS-specific */ |
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ |
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ |
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ |
#define PT_LOSUNW 0x6ffffffa |
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ |
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ |
#define PT_HISUNW 0x6fffffff |
#define PT_HIOS 0x6fffffff /* End of OS-specific */ |
#define PT_LOPROC 0x70000000 /* Start of processor-specific */ |
#define PT_HIPROC 0x7fffffff /* End of processor-specific */ |
507,6 → 607,7 |
#define PF_X (1 << 0) /* Segment is executable */ |
#define PF_W (1 << 1) /* Segment is writable */ |
#define PF_R (1 << 2) /* Segment is readable */ |
#define PF_MASKOS 0x0ff00000 /* OS-specific */ |
#define PF_MASKPROC 0xf0000000 /* Processor-specific */ |
/* Legal values for note segment descriptor types for core files. */ |
515,9 → 616,11 |
#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ |
#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ |
#define NT_PRXREG 4 /* Contains copy of prxregset struct */ |
#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ |
#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ |
#define NT_AUXV 6 /* Contains copy of auxv array */ |
#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ |
#define NT_ASRS 8 /* Contains copy of asrset struct */ |
#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ |
#define NT_PSINFO 13 /* Contains copy of psinfo struct */ |
#define NT_PRCRED 14 /* Contains copy of prcred struct */ |
524,6 → 627,26 |
#define NT_UTSNAME 15 /* Contains copy of utsname struct */ |
#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ |
#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ |
#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ |
#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ |
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ |
#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ |
#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ |
#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ |
#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ |
#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ |
#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ |
#define NT_S390_TIMER 0x301 /* s390 timer register */ |
#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ |
#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ |
#define NT_S390_CTRS 0x304 /* s390 control registers */ |
#define NT_S390_PREFIX 0x305 /* s390 prefix register */ |
#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ |
#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ |
#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ |
#define NT_ARM_TLS 0x401 /* ARM TLS register */ |
#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ |
#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ |
/* Legal values for the note segment descriptor types for object files. */ |
569,7 → 692,7 |
#define DT_INIT 12 /* Address of init function */ |
#define DT_FINI 13 /* Address of termination function */ |
#define DT_SONAME 14 /* Name of shared object */ |
#define DT_RPATH 15 /* Library search path */ |
#define DT_RPATH 15 /* Library search path (deprecated) */ |
#define DT_SYMBOLIC 16 /* Start symbol search here */ |
#define DT_REL 17 /* Address of Rel relocs */ |
#define DT_RELSZ 18 /* Total size of Rel relocs */ |
583,9 → 706,14 |
#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ |
#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ |
#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ |
#define DT_NUM 29 /* Number used */ |
#define DT_LOOS 0x60000000 /* Start of OS-specific */ |
#define DT_HIOS 0x6fffffff /* End of OS-specific */ |
#define DT_RUNPATH 29 /* Library search path */ |
#define DT_FLAGS 30 /* Flags for the object being loaded */ |
#define DT_ENCODING 32 /* Start of encoded range */ |
#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ |
#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ |
#define DT_NUM 34 /* Number used */ |
#define DT_LOOS 0x6000000d /* Start of OS-specific */ |
#define DT_HIOS 0x6ffff000 /* End of OS-specific */ |
#define DT_LOPROC 0x70000000 /* Start of processor-specific */ |
#define DT_HIPROC 0x7fffffff /* End of processor-specific */ |
#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ |
594,11 → 722,21 |
Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's |
approach. */ |
#define DT_VALRNGLO 0x6ffffd00 |
#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ |
#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ |
#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ |
#define DT_CHECKSUM 0x6ffffdf8 |
#define DT_PLTPADSZ 0x6ffffdf9 |
#define DT_MOVEENT 0x6ffffdfa |
#define DT_MOVESZ 0x6ffffdfb |
#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ |
#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting |
the following DT_* entry. */ |
#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ |
#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ |
#define DT_VALRNGHI 0x6ffffdff |
#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ |
#define DT_VALNUM 12 |
/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the |
Dyn.d_un.d_ptr field of the Elf*_Dyn structure. |
606,13 → 744,28 |
If any adjustment is made to the ELF object after it has been |
built these entries will need to be adjusted. */ |
#define DT_ADDRRNGLO 0x6ffffe00 |
#define DT_SYMINFO 0x6ffffeff /* syminfo table */ |
#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ |
#define DT_TLSDESC_PLT 0x6ffffef6 |
#define DT_TLSDESC_GOT 0x6ffffef7 |
#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ |
#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ |
#define DT_CONFIG 0x6ffffefa /* Configuration information. */ |
#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ |
#define DT_AUDIT 0x6ffffefc /* Object auditing. */ |
#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ |
#define DT_MOVETAB 0x6ffffefe /* Move table. */ |
#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ |
#define DT_ADDRRNGHI 0x6ffffeff |
#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ |
#define DT_ADDRNUM 11 |
/* The versioning entry types. The next are defined as part of the |
GNU extension. */ |
#define DT_VERSYM 0x6ffffff0 |
#define DT_RELACOUNT 0x6ffffff9 |
#define DT_RELCOUNT 0x6ffffffa |
/* These were chosen by Sun. */ |
#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ |
#define DT_VERDEF 0x6ffffffc /* Address of version definition |
631,6 → 784,13 |
#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) |
#define DT_EXTRANUM 3 |
/* Values of `d_un.d_val' in the DT_FLAGS entry. */ |
#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ |
#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ |
#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ |
#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ |
#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ |
/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 |
entry in the dynamic section. */ |
#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ |
640,7 → 800,35 |
#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ |
#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ |
#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ |
#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ |
#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ |
#define DF_1_TRANS 0x00000200 |
#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ |
#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ |
#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ |
#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ |
#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ |
#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ |
#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ |
#define DF_1_NODIRECT 0x00020000 /* Object has no-direct binding. */ |
#define DF_1_IGNMULDEF 0x00040000 |
#define DF_1_NOKSYMS 0x00080000 |
#define DF_1_NOHDR 0x00100000 |
#define DF_1_EDITED 0x00200000 /* Object is modified after built. */ |
#define DF_1_NORELOC 0x00400000 |
#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */ |
#define DF_1_GLOBAUDIT 0x01000000 /* Global auditin required. */ |
#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */ |
/* Flags for the feature selection in DT_FEATURE_1. */ |
#define DTF_1_PARINIT 0x00000001 |
#define DTF_1_CONFEXP 0x00000002 |
/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ |
#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ |
#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not |
generally available. */ |
/* Version definition sections. */ |
typedef struct |
677,6 → 865,12 |
#define VER_FLG_BASE 0x1 /* Version definition of file itself */ |
#define VER_FLG_WEAK 0x2 /* Weak version identifier */ |
/* Versym symbol index values. */ |
#define VER_NDX_LOCAL 0 /* Symbol is local. */ |
#define VER_NDX_GLOBAL 1 /* Symbol is global. */ |
#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ |
#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ |
/* Auxialiary version information. */ |
typedef struct |
762,23 → 956,25 |
typedef struct |
{ |
int a_type; /* Entry type */ |
uint32_t a_type; /* Entry type */ |
union |
{ |
long int a_val; /* Integer value */ |
void *a_ptr; /* Pointer value */ |
void (*a_fcn) (void); /* Function pointer value */ |
uint32_t a_val; /* Integer value */ |
/* We use to have pointer elements added here. We cannot do that, |
though, since it does not work when using 32-bit definitions |
on 64-bit platforms and vice versa. */ |
} a_un; |
} Elf32_auxv_t; |
typedef struct |
{ |
long int a_type; /* Entry type */ |
uint64_t a_type; /* Entry type */ |
union |
{ |
long int a_val; /* Integer value */ |
void *a_ptr; /* Pointer value */ |
void (*a_fcn) (void); /* Function pointer value */ |
uint64_t a_val; /* Integer value */ |
/* We use to have pointer elements added here. We cannot do that, |
though, since it does not work when using 32-bit definitions |
on 64-bit platforms and vice versa. */ |
} a_un; |
} Elf64_auxv_t; |
799,6 → 995,7 |
#define AT_EUID 12 /* Effective uid */ |
#define AT_GID 13 /* Real gid */ |
#define AT_EGID 14 /* Effective gid */ |
#define AT_CLKTCK 17 /* Frequency of times() */ |
/* Some more special a_type values describing the hardware. */ |
#define AT_PLATFORM 15 /* String identifying platform. */ |
807,9 → 1004,37 |
/* This entry gives some information about the FPU initialization |
performed by the kernel. */ |
#define AT_FPUCW 17 /* Used FPU control word. */ |
#define AT_FPUCW 18 /* Used FPU control word. */ |
/* Cache block sizes. */ |
#define AT_DCACHEBSIZE 19 /* Data cache block size. */ |
#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ |
#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ |
/* A special ignored value for PPC, used by the kernel to control the |
interpretation of the AUXV. Must be > 16. */ |
#define AT_IGNOREPPC 22 /* Entry should be ignored. */ |
#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ |
#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ |
#define AT_RANDOM 25 /* Address of 16 random bytes. */ |
#define AT_EXECFN 31 /* Filename of executable. */ |
/* Pointer to the global system page used for system calls and other |
nice things. */ |
#define AT_SYSINFO 32 |
#define AT_SYSINFO_EHDR 33 |
/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains |
log2 of line size; mask those to get cache size. */ |
#define AT_L1I_CACHESHAPE 34 |
#define AT_L1D_CACHESHAPE 35 |
#define AT_L2_CACHESHAPE 36 |
#define AT_L3_CACHESHAPE 37 |
/* Note section contents. Each entry in the note section begins with |
a header of a fixed form. */ |
850,17 → 1075,66 |
word 2: minor version of the ABI |
word 3: subminor version of the ABI |
*/ |
#define ELF_NOTE_ABI 1 |
#define NT_GNU_ABI_TAG 1 |
#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ |
/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI |
note section entry. */ |
/* Known OSes. These values can appear in word 0 of an |
NT_GNU_ABI_TAG note section entry. */ |
#define ELF_NOTE_OS_LINUX 0 |
#define ELF_NOTE_OS_GNU 1 |
#define ELF_NOTE_OS_SOLARIS2 2 |
#define ELF_NOTE_OS_FREEBSD 3 |
/* Synthetic hwcap information. The descriptor begins with two words: |
word 0: number of entries |
word 1: bitmask of enabled entries |
Then follow variable-length entries, one byte followed by a |
'\0'-terminated hwcap name string. The byte gives the bit |
number to test if enabled, (1U << bit) & bitmask. */ |
#define NT_GNU_HWCAP 2 |
/* Build ID bits as generated by ld --build-id. |
The descriptor consists of any nonzero number of bytes. */ |
#define NT_GNU_BUILD_ID 3 |
/* Version note generated by GNU gold containing a version string. */ |
#define NT_GNU_GOLD_VERSION 4 |
/* Move records. */ |
typedef struct |
{ |
Elf32_Xword m_value; /* Symbol value. */ |
Elf32_Word m_info; /* Size and index. */ |
Elf32_Word m_poffset; /* Symbol offset. */ |
Elf32_Half m_repeat; /* Repeat count. */ |
Elf32_Half m_stride; /* Stride info. */ |
} Elf32_Move; |
typedef struct |
{ |
Elf64_Xword m_value; /* Symbol value. */ |
Elf64_Xword m_info; /* Size and index. */ |
Elf64_Xword m_poffset; /* Symbol offset. */ |
Elf64_Half m_repeat; /* Repeat count. */ |
Elf64_Half m_stride; /* Stride info. */ |
} Elf64_Move; |
/* Macro to construct move records. */ |
#define ELF32_M_SYM(info) ((info) >> 8) |
#define ELF32_M_SIZE(info) ((unsigned char) (info)) |
#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) |
#define ELF64_M_SYM(info) ELF32_M_SYM (info) |
#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) |
#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) |
/* Motorola 68k specific definitions. */ |
/* Values for Elf32_Ehdr.e_flags. */ |
#define EF_CPU32 0x00810000 |
/* m68k relocs. */ |
#define R_68K_NONE 0 /* No reloc */ |
886,8 → 1160,29 |
#define R_68K_GLOB_DAT 20 /* Create GOT entry */ |
#define R_68K_JMP_SLOT 21 /* Create PLT entry */ |
#define R_68K_RELATIVE 22 /* Adjust by program base */ |
#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ |
#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ |
#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ |
#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ |
#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ |
#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ |
#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ |
#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ |
#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ |
#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ |
#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ |
#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ |
#define R_68K_TLS_LE32 37 /* 32 bit offset relative to |
static TLS block */ |
#define R_68K_TLS_LE16 38 /* 16 bit offset relative to |
static TLS block */ |
#define R_68K_TLS_LE8 39 /* 8 bit offset relative to |
static TLS block */ |
#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ |
#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ |
#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ |
/* Keep this the last entry. */ |
#define R_68K_NUM 23 |
#define R_68K_NUM 43 |
/* Intel 80386 specific definitions. */ |
904,11 → 1199,63 |
#define R_386_RELATIVE 8 /* Adjust by program base */ |
#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ |
#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ |
#define R_386_32PLT 11 |
#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ |
#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS |
block offset */ |
#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block |
offset */ |
#define R_386_TLS_LE 17 /* Offset relative to static TLS |
block */ |
#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of |
general dynamic thread local data */ |
#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of |
local dynamic thread local data |
in LE code */ |
#define R_386_16 20 |
#define R_386_PC16 21 |
#define R_386_8 22 |
#define R_386_PC8 23 |
#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic |
thread local data */ |
#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ |
#define R_386_TLS_GD_CALL 26 /* Relocation for call to |
__tls_get_addr() */ |
#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ |
#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic |
thread local data in LE code */ |
#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ |
#define R_386_TLS_LDM_CALL 30 /* Relocation for call to |
__tls_get_addr() in LDM code */ |
#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ |
#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ |
#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS |
block offset */ |
#define R_386_TLS_LE_32 34 /* Negated offset relative to static |
TLS block */ |
#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ |
#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ |
#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ |
/* 38? */ |
#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ |
#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS |
descriptor for |
relaxation. */ |
#define R_386_TLS_DESC 41 /* TLS descriptor containing |
pointer to code and to |
argument, returning the TLS |
offset for the symbol. */ |
#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ |
#define R_386_GOT32X 43 /* 32 bit GOT entry, relaxable */ |
/* Keep this the last entry. */ |
#define R_386_NUM 11 |
#define R_386_NUM 44 |
/* SUN SPARC specific definitions. */ |
/* Legal values for ST_TYPE subfield of st_info (symbol type). */ |
#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ |
/* Values for Elf64_Ehdr.e_flags. */ |
#define EF_SPARCV9_MM 3 |
915,9 → 1262,12 |
#define EF_SPARCV9_TSO 0 |
#define EF_SPARCV9_PSO 1 |
#define EF_SPARCV9_RMO 2 |
#define EF_SPARC_LEDATA 0x800000 /* little endian data */ |
#define EF_SPARC_EXT_MASK 0xFFFF00 |
#define EF_SPARC_SUN_US1 0x000200 |
#define EF_SPARC_HAL_R1 0x000400 |
#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ |
#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ |
#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ |
#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ |
/* SPARC relocs. */ |
957,7 → 1307,7 |
#define R_SPARC_10 30 /* Direct 10 bit */ |
#define R_SPARC_11 31 /* Direct 11 bit */ |
#define R_SPARC_64 32 /* Direct 64 bit */ |
#define R_SPARC_OLO10 33 /* ?? */ |
#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ |
#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ |
#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ |
#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ |
966,6 → 1316,7 |
#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ |
#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ |
#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ |
#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */ |
#define R_SPARC_7 43 /* Direct 7 bit */ |
#define R_SPARC_5 44 /* Direct 5 bit */ |
#define R_SPARC_6 45 /* Direct 6 bit */ |
979,8 → 1330,46 |
#define R_SPARC_REGISTER 53 /* Global register usage */ |
#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ |
#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ |
#define R_SPARC_TLS_GD_HI22 56 |
#define R_SPARC_TLS_GD_LO10 57 |
#define R_SPARC_TLS_GD_ADD 58 |
#define R_SPARC_TLS_GD_CALL 59 |
#define R_SPARC_TLS_LDM_HI22 60 |
#define R_SPARC_TLS_LDM_LO10 61 |
#define R_SPARC_TLS_LDM_ADD 62 |
#define R_SPARC_TLS_LDM_CALL 63 |
#define R_SPARC_TLS_LDO_HIX22 64 |
#define R_SPARC_TLS_LDO_LOX10 65 |
#define R_SPARC_TLS_LDO_ADD 66 |
#define R_SPARC_TLS_IE_HI22 67 |
#define R_SPARC_TLS_IE_LO10 68 |
#define R_SPARC_TLS_IE_LD 69 |
#define R_SPARC_TLS_IE_LDX 70 |
#define R_SPARC_TLS_IE_ADD 71 |
#define R_SPARC_TLS_LE_HIX22 72 |
#define R_SPARC_TLS_LE_LOX10 73 |
#define R_SPARC_TLS_DTPMOD32 74 |
#define R_SPARC_TLS_DTPMOD64 75 |
#define R_SPARC_TLS_DTPOFF32 76 |
#define R_SPARC_TLS_DTPOFF64 77 |
#define R_SPARC_TLS_TPOFF32 78 |
#define R_SPARC_TLS_TPOFF64 79 |
#define R_SPARC_GOTDATA_HIX22 80 |
#define R_SPARC_GOTDATA_LOX10 81 |
#define R_SPARC_GOTDATA_OP_HIX22 82 |
#define R_SPARC_GOTDATA_OP_LOX10 83 |
#define R_SPARC_GOTDATA_OP 84 |
#define R_SPARC_H34 85 |
#define R_SPARC_SIZE32 86 |
#define R_SPARC_SIZE64 87 |
#define R_SPARC_WDISP10 88 |
#define R_SPARC_JMP_IREL 248 |
#define R_SPARC_IRELATIVE 249 |
#define R_SPARC_GNU_VTINHERIT 250 |
#define R_SPARC_GNU_VTENTRY 251 |
#define R_SPARC_REV32 252 |
/* Keep this the last entry. */ |
#define R_SPARC_NUM 56 |
#define R_SPARC_NUM 253 |
/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ |
987,14 → 1376,6 |
#define DT_SPARC_REGISTER 0x70000001 |
#define DT_SPARC_NUM 2 |
/* Bits present in AT_HWCAP, primarily for Sparc32. */ |
#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ |
#define HWCAP_SPARC_STBAR 2 |
#define HWCAP_SPARC_SWAP 4 |
#define HWCAP_SPARC_MULDIV 8 |
#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ |
/* MIPS R3000 specific definitions. */ |
/* Legal values for e_flags field of Elf32_Ehdr. */ |
1015,6 → 1396,8 |
#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ |
#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ |
#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ |
#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ |
#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ |
/* The following are non-official names and should not be used. */ |
1023,6 → 1406,8 |
#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ |
#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ |
#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ |
#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ |
#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ |
/* Special section indices. */ |
1093,6 → 1478,7 |
#define STO_MIPS_INTERNAL 0x1 |
#define STO_MIPS_HIDDEN 0x2 |
#define STO_MIPS_PROTECTED 0x3 |
#define STO_MIPS_PLT 0x8 |
#define STO_MIPS_SC_ALIGN_UNUSED 0xff |
/* MIPS specific values for `st_info'. */ |
1225,8 → 1611,24 |
#define R_MIPS_PJUMP 35 |
#define R_MIPS_RELGOT 36 |
#define R_MIPS_JALR 37 |
#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ |
#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ |
#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ |
#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ |
#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ |
#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ |
#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ |
#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ |
#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ |
#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ |
#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ |
#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ |
#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ |
#define R_MIPS_GLOB_DAT 51 |
#define R_MIPS_COPY 126 |
#define R_MIPS_JUMP_SLOT 127 |
/* Keep this the last entry. */ |
#define R_MIPS_NUM 38 |
#define R_MIPS_NUM 128 |
/* Legal values for p_type field of Elf32_Phdr. */ |
1292,7 → 1694,13 |
#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ |
#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ |
#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ |
#define DT_MIPS_NUM 0x32 |
/* The address of .got.plt in an executable using the new non-PIC ABI. */ |
#define DT_MIPS_PLTGOT 0x70000032 |
/* The base of the PLT in an executable using the new non-PIC ABI if that |
PLT is writable. For a non-writable PLT, this is omitted or has a zero |
value. */ |
#define DT_MIPS_RWPLT 0x70000034 |
#define DT_MIPS_NUM 0x35 |
/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ |
1353,38 → 1761,46 |
/* Legal values for e_flags field of Elf32_Ehdr. */ |
#define EF_PARISC_TRAPNL 1 /* Trap nil pointer dereference. */ |
#define EF_PARISC_EXT 2 /* Program uses arch. extensions. */ |
#define EF_PARISC_ARCH 0xffff0000 /* Architecture version. */ |
/* Defined values are: |
0x020b PA-RISC 1.0 big-endian |
0x0210 PA-RISC 1.1 big-endian |
0x028b PA-RISC 1.0 little-endian |
0x0290 PA-RISC 1.1 little-endian |
*/ |
#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ |
#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ |
#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ |
#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ |
#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch |
prediction. */ |
#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ |
#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ |
/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ |
#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ |
#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ |
#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ |
/* Additional section indeces. */ |
#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared |
symbols in ANSI C. */ |
#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ |
/* Legal values for sh_type field of Elf32_Shdr. */ |
#define SHT_PARISC_GOT 0x70000000 /* GOT for external data. */ |
#define SHT_PARISC_ARCH 0x70000001 /* Architecture extensions. */ |
#define SHT_PARISC_GLOBAL 0x70000002 /* Definition of $global$. */ |
#define SHT_PARISC_MILLI 0x70000003 /* Millicode routines. */ |
#define SHT_PARISC_UNWIND 0x70000004 /* Unwind information. */ |
#define SHT_PARISC_PLT 0x70000005 /* Procedure linkage table. */ |
#define SHT_PARISC_SDATA 0x70000006 /* Short initialized data. */ |
#define SHT_PARISC_SBSS 0x70000007 /* Short uninitialized data. */ |
#define SHT_PARISC_SYMEXTN 0x70000008 /* Argument/relocation info. */ |
#define SHT_PARISC_STUBS 0x70000009 /* Linker stubs. */ |
#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ |
#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ |
#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ |
/* Legal values for sh_flags field of Elf32_Shdr. */ |
#define SHF_PARISC_GLOBAL 0x10000000 /* Section defines dp. */ |
#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ |
#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ |
#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ |
/* Legal values for ST_TYPE subfield of st_info (symbol type). */ |
#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ |
#define STT_HP_OPAQUE (STT_LOOS + 0x1) |
#define STT_HP_STUB (STT_LOOS + 0x2) |
/* HPPA relocs. */ |
#define R_PARISC_NONE 0 /* No reloc. */ |
1391,27 → 1807,147 |
#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ |
#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ |
#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ |
#define R_PARISC_DIR14R 4 /* Right 14 bits of eff. address. */ |
#define R_PARISC_PCREL21L 5 /* PC-relative, left 21 bits. */ |
#define R_PARISC_PCREL14R 6 /* PC-relative, right 14 bits. */ |
#define R_PARISC_PCREL17C 7 /* Conditional PC-relative, ignore |
if displacement > 17bits. */ |
#define R_PARISC_PCREL17F 8 /* Conditional PC-relative, must |
fit in 17bits. */ |
#define R_PARISC_DPREL21L 9 /* DP-relative, left 21 bits. */ |
#define R_PARISC_DPREL14R 10 /* DP-relative, right 14 bits. */ |
#define R_PARISC_DPREL14F 11 /* DP-relative, must bit in 14 bits. */ |
#define R_PARISC_DLTREL21L 12 /* DLT-relative, left 21 bits. */ |
#define R_PARISC_DLTREL14R 13 /* DLT-relative, right 14 bits. */ |
#define R_PARISC_DLTREL14F 14 /* DLT-relative, must fit in 14 bits.*/ |
#define R_PARISC_DLTIND21L 15 /* DLT-relative indirect, left |
21 bits. */ |
#define R_PARISC_DLTIND14R 16 /* DLT-relative indirect, right |
14 bits. */ |
#define R_PARISC_DLTIND14F 17 /* DLT-relative indirect, must fit |
int 14 bits. */ |
#define R_PARISC_PLABEL32 18 /* Direct 32-bit reference to proc. */ |
#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ |
#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ |
#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ |
#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ |
#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ |
#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ |
#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ |
#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ |
#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ |
#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ |
#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ |
#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ |
#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ |
#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ |
#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ |
#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ |
#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ |
#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ |
#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ |
#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ |
#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ |
#define R_PARISC_FPTR64 64 /* 64 bits function address. */ |
#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ |
#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */ |
#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */ |
#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ |
#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ |
#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ |
#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ |
#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ |
#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ |
#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ |
#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ |
#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ |
#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ |
#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ |
#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ |
#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ |
#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ |
#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ |
#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ |
#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ |
#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ |
#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ |
#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ |
#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ |
#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ |
#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ |
#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ |
#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ |
#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ |
#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ |
#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ |
#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ |
#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ |
#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ |
#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ |
#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ |
#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ |
#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ |
#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ |
#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ |
#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ |
#define R_PARISC_LORESERVE 128 |
#define R_PARISC_COPY 128 /* Copy relocation. */ |
#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ |
#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ |
#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ |
#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ |
#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ |
#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ |
#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ |
#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ |
#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ |
#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ |
#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ |
#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ |
#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ |
#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ |
#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ |
#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ |
#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ |
#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ |
#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ |
#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ |
#define R_PARISC_GNU_VTENTRY 232 |
#define R_PARISC_GNU_VTINHERIT 233 |
#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */ |
#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */ |
#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */ |
#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */ |
#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */ |
#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */ |
#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */ |
#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */ |
#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */ |
#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */ |
#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */ |
#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */ |
#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L |
#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R |
#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L |
#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R |
#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 |
#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 |
#define R_PARISC_HIRESERVE 255 |
/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ |
#define PT_HP_TLS (PT_LOOS + 0x0) |
#define PT_HP_CORE_NONE (PT_LOOS + 0x1) |
#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) |
#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) |
#define PT_HP_CORE_COMM (PT_LOOS + 0x4) |
#define PT_HP_CORE_PROC (PT_LOOS + 0x5) |
#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) |
#define PT_HP_CORE_STACK (PT_LOOS + 0x7) |
#define PT_HP_CORE_SHM (PT_LOOS + 0x8) |
#define PT_HP_CORE_MMF (PT_LOOS + 0x9) |
#define PT_HP_PARALLEL (PT_LOOS + 0x10) |
#define PT_HP_FASTBIND (PT_LOOS + 0x11) |
#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) |
#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) |
#define PT_HP_STACK (PT_LOOS + 0x14) |
#define PT_PARISC_ARCHEXT 0x70000000 |
#define PT_PARISC_UNWIND 0x70000001 |
/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ |
#define PF_PARISC_SBP 0x08000000 |
#define PF_HP_PAGE_SIZE 0x00100000 |
#define PF_HP_FAR_SHARED 0x00200000 |
#define PF_HP_NEAR_SHARED 0x00400000 |
#define PF_HP_CODE 0x01000000 |
#define PF_HP_MODIFY 0x02000000 |
#define PF_HP_LAZYSWAP 0x04000000 |
#define PF_HP_SBP 0x08000000 |
/* Alpha specific definitions. */ |
/* Legal values for e_flags field of Elf64_Ehdr. */ |
1447,28 → 1983,52 |
#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ |
#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ |
#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ |
#define R_ALPHA_OP_PUSH 12 /* OP stack push */ |
#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ |
#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ |
#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ |
#define R_ALPHA_GPVALUE 16 |
#define R_ALPHA_GPRELHIGH 17 |
#define R_ALPHA_GPRELLOW 18 |
#define R_ALPHA_IMMED_GP_16 19 |
#define R_ALPHA_IMMED_GP_HI32 20 |
#define R_ALPHA_IMMED_SCN_HI32 21 |
#define R_ALPHA_IMMED_BR_HI32 22 |
#define R_ALPHA_IMMED_LO32 23 |
#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ |
#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ |
#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ |
#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ |
#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ |
#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ |
#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ |
#define R_ALPHA_TLS_GD_HI 28 |
#define R_ALPHA_TLSGD 29 |
#define R_ALPHA_TLS_LDM 30 |
#define R_ALPHA_DTPMOD64 31 |
#define R_ALPHA_GOTDTPREL 32 |
#define R_ALPHA_DTPREL64 33 |
#define R_ALPHA_DTPRELHI 34 |
#define R_ALPHA_DTPRELLO 35 |
#define R_ALPHA_DTPREL16 36 |
#define R_ALPHA_GOTTPREL 37 |
#define R_ALPHA_TPREL64 38 |
#define R_ALPHA_TPRELHI 39 |
#define R_ALPHA_TPRELLO 40 |
#define R_ALPHA_TPREL16 41 |
/* Keep this the last entry. */ |
#define R_ALPHA_NUM 28 |
#define R_ALPHA_NUM 46 |
/* Magic values of the LITUSE relocation addend. */ |
#define LITUSE_ALPHA_ADDR 0 |
#define LITUSE_ALPHA_BASE 1 |
#define LITUSE_ALPHA_BYTOFF 2 |
#define LITUSE_ALPHA_JSR 3 |
#define LITUSE_ALPHA_TLS_GD 4 |
#define LITUSE_ALPHA_TLS_LDM 5 |
/* Legal values for d_tag of Elf64_Dyn. */ |
#define DT_ALPHA_PLTRO (DT_LOPROC + 0) |
#define DT_ALPHA_NUM 1 |
/* PowerPC specific declarations */ |
/* Values for Elf32/64_Ehdr.e_flags. */ |
#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ |
/* Cygnus local bits below */ |
#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ |
#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib |
flag */ |
/* PowerPC relocations defined by the ABIs */ |
#define R_PPC_NONE 0 |
#define R_PPC_ADDR32 1 /* 32bit absolute address */ |
1507,9 → 2067,37 |
#define R_PPC_SECTOFF_LO 34 |
#define R_PPC_SECTOFF_HI 35 |
#define R_PPC_SECTOFF_HA 36 |
/* Keep this the last entry. */ |
#define R_PPC_NUM 37 |
/* PowerPC relocations defined for the TLS access ABI. */ |
#define R_PPC_TLS 67 /* none (sym+add)@tls */ |
#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ |
#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ |
#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ |
#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ |
#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ |
#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ |
#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ |
#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ |
#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ |
#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ |
#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ |
#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ |
#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ |
#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ |
#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ |
#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ |
#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ |
#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ |
#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ |
#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ |
#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ |
#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ |
#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ |
#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ |
#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ |
#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ |
#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ |
/* The remaining relocs are from the Embedded ELF ABI, and are not |
in the SVR4 ELF ABI. */ |
#define R_PPC_EMB_NADDR32 101 |
1537,11 → 2125,150 |
#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ |
#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ |
/* GNU extension to support local ifunc. */ |
#define R_PPC_IRELATIVE 248 |
/* GNU relocs used in PIC code sequences. */ |
#define R_PPC_REL16 249 /* half16 (sym+add-.) */ |
#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ |
#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ |
#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ |
/* This is a phony reloc to handle any old fashioned TOC16 references |
that may still be in object files. */ |
#define R_PPC_TOC16 255 |
/* PowerPC specific values for the Dyn d_tag field. */ |
#define DT_PPC_GOT (DT_LOPROC + 0) |
#define DT_PPC_NUM 1 |
/* PowerPC64 relocations defined by the ABIs */ |
#define R_PPC64_NONE R_PPC_NONE |
#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ |
#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ |
#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ |
#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ |
#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ |
#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ |
#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ |
#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN |
#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN |
#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ |
#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ |
#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN |
#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN |
#define R_PPC64_GOT16 R_PPC_GOT16 |
#define R_PPC64_GOT16_LO R_PPC_GOT16_LO |
#define R_PPC64_GOT16_HI R_PPC_GOT16_HI |
#define R_PPC64_GOT16_HA R_PPC_GOT16_HA |
#define R_PPC64_COPY R_PPC_COPY |
#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT |
#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT |
#define R_PPC64_RELATIVE R_PPC_RELATIVE |
#define R_PPC64_UADDR32 R_PPC_UADDR32 |
#define R_PPC64_UADDR16 R_PPC_UADDR16 |
#define R_PPC64_REL32 R_PPC_REL32 |
#define R_PPC64_PLT32 R_PPC_PLT32 |
#define R_PPC64_PLTREL32 R_PPC_PLTREL32 |
#define R_PPC64_PLT16_LO R_PPC_PLT16_LO |
#define R_PPC64_PLT16_HI R_PPC_PLT16_HI |
#define R_PPC64_PLT16_HA R_PPC_PLT16_HA |
#define R_PPC64_SECTOFF R_PPC_SECTOFF |
#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO |
#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI |
#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA |
#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ |
#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ |
#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ |
#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ |
#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ |
#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ |
#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ |
#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ |
#define R_PPC64_PLT64 45 /* doubleword64 L + A */ |
#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ |
#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ |
#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ |
#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ |
#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ |
#define R_PPC64_TOC 51 /* doubleword64 .TOC */ |
#define R_PPC64_PLTGOT16 52 /* half16* M + A */ |
#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ |
#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ |
#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ |
#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ |
#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ |
#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ |
#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ |
#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ |
#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ |
#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ |
#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ |
#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ |
#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ |
#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ |
/* PowerPC64 relocations defined for the TLS access ABI. */ |
#define R_PPC64_TLS 67 /* none (sym+add)@tls */ |
#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ |
#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ |
#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ |
#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ |
#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ |
#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ |
#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ |
#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ |
#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ |
#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ |
#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ |
#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ |
#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ |
#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ |
#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ |
#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ |
#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ |
#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ |
#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ |
#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ |
#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ |
#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ |
#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ |
#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ |
#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ |
#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ |
#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ |
#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ |
#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ |
#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ |
#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ |
#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ |
#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ |
#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ |
#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ |
#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ |
#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ |
#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ |
#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ |
/* GNU extension to support local ifunc. */ |
#define R_PPC64_JMP_IREL 247 |
#define R_PPC64_IRELATIVE 248 |
#define R_PPC64_REL16 249 /* half16 (sym+add-.) */ |
#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */ |
#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ |
#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ |
/* PowerPC64 specific values for the Dyn d_tag field. */ |
#define DT_PPC64_GLINK (DT_LOPROC + 0) |
#define DT_PPC64_OPD (DT_LOPROC + 1) |
#define DT_PPC64_OPDSZ (DT_LOPROC + 2) |
#define DT_PPC64_NUM 3 |
/* ARM specific declarations */ |
/* Processor specific flags for the ELF header e_flags field. */ |
1551,23 → 2278,188 |
#define EF_ARM_APCS_26 0x08 |
#define EF_ARM_APCS_FLOAT 0x10 |
#define EF_ARM_PIC 0x20 |
#define EF_ALIGN8 0x40 /* 8-bit structure alignment is in use */ |
#define EF_NEW_ABI 0x80 |
#define EF_OLD_ABI 0x100 |
#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ |
#define EF_ARM_NEW_ABI 0x80 |
#define EF_ARM_OLD_ABI 0x100 |
#define EF_ARM_SOFT_FLOAT 0x200 |
#define EF_ARM_VFP_FLOAT 0x400 |
#define EF_ARM_MAVERICK_FLOAT 0x800 |
/* Additional symbol types for Thumb */ |
#define STT_ARM_TFUNC 0xd |
#define EF_ARM_ABI_FLOAT_SOFT 0x200 /* NB conflicts with EF_ARM_SOFT_FLOAT */ |
#define EF_ARM_ABI_FLOAT_HARD 0x400 /* NB conflicts with EF_ARM_VFP_FLOAT */ |
/* Other constants defined in the ARM ELF spec. version B-01. */ |
/* NB. These conflict with values defined above. */ |
#define EF_ARM_SYMSARESORTED 0x04 |
#define EF_ARM_DYNSYMSUSESEGIDX 0x08 |
#define EF_ARM_MAPSYMSFIRST 0x10 |
#define EF_ARM_EABIMASK 0XFF000000 |
/* Constants defined in AAELF. */ |
#define EF_ARM_BE8 0x00800000 |
#define EF_ARM_LE8 0x00400000 |
#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) |
#define EF_ARM_EABI_UNKNOWN 0x00000000 |
#define EF_ARM_EABI_VER1 0x01000000 |
#define EF_ARM_EABI_VER2 0x02000000 |
#define EF_ARM_EABI_VER3 0x03000000 |
#define EF_ARM_EABI_VER4 0x04000000 |
#define EF_ARM_EABI_VER5 0x05000000 |
/* Additional symbol types for Thumb. */ |
#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ |
#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ |
/* ARM-specific values for sh_flags */ |
#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ |
#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined |
in the input to a link step */ |
in the input to a link step. */ |
/* ARM-specific program header flags */ |
#define PF_ARM_SB 0x10000000 /* Segment contains the location |
addressed by the static base */ |
addressed by the static base. */ |
#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ |
#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ |
/* Processor specific values for the Phdr p_type field. */ |
#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ |
/* Processor specific values for the Shdr sh_type field. */ |
#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ |
#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ |
#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ |
/* AArch64 relocs. */ |
#define R_AARCH64_NONE 0 /* No relocation. */ |
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */ |
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */ |
#define R_AARCH64_ABS16 259 /* Direct 16-bit. */ |
#define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */ |
#define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */ |
#define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */ |
#define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */ |
#define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */ |
#define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */ |
#define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */ |
#define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */ |
#define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */ |
#define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */ |
#define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */ |
#define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */ |
#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */ |
#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */ |
#define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */ |
#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */ |
#define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */ |
#define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */ |
#define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */ |
#define R_AARCH64_CALL26 283 /* Likewise for CALL. */ |
#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */ |
#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */ |
#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */ |
#define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */ |
#define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */ |
#define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */ |
#define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */ |
#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */ |
#define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */ |
#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */ |
#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */ |
#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */ |
#define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */ |
#define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */ |
#define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */ |
#define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */ |
#define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */ |
#define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */ |
#define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */ |
#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */ |
#define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */ |
#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */ |
#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */ |
#define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */ |
#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */ |
#define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */ |
#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */ |
#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */ |
#define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */ |
#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */ |
#define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */ |
#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */ |
#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */ |
#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */ |
#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */ |
#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */ |
#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */ |
#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */ |
#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */ |
#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */ |
#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */ |
#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */ |
#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */ |
#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */ |
#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */ |
#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */ |
#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */ |
#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */ |
#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */ |
#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */ |
#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */ |
#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */ |
#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */ |
#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */ |
#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */ |
#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */ |
#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */ |
#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */ |
#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */ |
#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */ |
#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */ |
#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */ |
#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */ |
#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */ |
#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */ |
#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */ |
#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */ |
#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */ |
#define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */ |
#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */ |
#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */ |
#define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */ |
#define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */ |
#define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */ |
#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */ |
#define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */ |
#define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */ |
#define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */ |
#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */ |
#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */ |
#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */ |
#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */ |
#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ |
#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */ |
#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */ |
#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ |
#define R_AARCH64_TLS_DTPMOD64 1028 /* Module number, 64 bit. */ |
#define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */ |
#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */ |
#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ |
#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */ |
/* ARM relocs. */ |
#define R_ARM_NONE 0 /* No reloc */ |
#define R_ARM_PC24 1 /* PC relative 26 bit branch */ |
#define R_ARM_ABS32 2 /* Direct 32 bit */ |
1581,10 → 2473,14 |
#define R_ARM_THM_PC22 10 |
#define R_ARM_THM_PC8 11 |
#define R_ARM_AMP_VCALL9 12 |
#define R_ARM_SWI24 13 |
#define R_ARM_SWI24 13 /* Obsolete static relocation. */ |
#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */ |
#define R_ARM_THM_SWI8 14 |
#define R_ARM_XPC25 15 |
#define R_ARM_THM_XPC22 16 |
#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ |
#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ |
#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ |
#define R_ARM_COPY 20 /* Copy symbol at runtime */ |
#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ |
#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ |
1593,10 → 2489,41 |
#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ |
#define R_ARM_GOT32 26 /* 32 bit GOT entry */ |
#define R_ARM_PLT32 27 /* 32 bit PLT address */ |
#define R_ARM_CALL 28 |
#define R_ARM_JUMP24 29 |
#define R_ARM_THM_JUMP24 30 |
#define R_ARM_ALU_PCREL_7_0 32 |
#define R_ARM_ALU_PCREL_15_8 33 |
#define R_ARM_ALU_PCREL_23_15 34 |
#define R_ARM_LDR_SBREL_11_0 35 |
#define R_ARM_ALU_SBREL_19_12 36 |
#define R_ARM_ALU_SBREL_27_20 37 |
#define R_ARM_V4BX 40 |
#define R_ARM_PREL31 42 |
#define R_ARM_MOVW_ABS_NC 43 |
#define R_ARM_MOVT_ABS 44 |
#define R_ARM_THM_MOVW_ABS_NC 47 |
#define R_ARM_THM_MOVT_ABS 48 |
#define R_ARM_TLS_GOTDESC 90 |
#define R_ARM_TLS_CALL 91 |
#define R_ARM_TLS_DESCSEQ 92 |
#define R_ARM_THM_TLS_CALL 93 |
#define R_ARM_GNU_VTENTRY 100 |
#define R_ARM_GNU_VTINHERIT 101 |
#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ |
#define R_ARM_THM_PC9 103 /* thumb conditional branch */ |
#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic |
thread local data */ |
#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic |
thread local data */ |
#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS |
block */ |
#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of |
static TLS block offset */ |
#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static |
TLS block */ |
#define R_ARM_THM_TLS_DESCSEQ 129 |
#define R_ARM_IRELATIVE 160 |
#define R_ARM_RXPC25 249 |
#define R_ARM_RSBREL32 250 |
#define R_ARM_THM_RPC22 251 |
1608,6 → 2535,7 |
#define R_ARM_NUM 256 |
/* TMS320C67xx specific declarations */ |
/* XXX: no ELF standard yet */ |
/* TMS320C67xx relocs. */ |
1621,7 → 2549,685 |
#define R_C60_GOTOFF 9 /* 32 bit offset to GOT */ |
#define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */ |
#define R_C60HI16 0x55 // high 16 bit MVKH embedded |
#define R_C60LO16 0x54 // low 16 bit MVKL embedded |
#define R_C60HI16 0x55 /* high 16 bit MVKH embedded */ |
#define R_C60LO16 0x54 /* low 16 bit MVKL embedded */ |
/* IA-64 specific declarations. */ |
/* Processor specific flags for the Ehdr e_flags field. */ |
#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ |
#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ |
#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ |
/* Processor specific values for the Phdr p_type field. */ |
#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ |
#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ |
#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) |
#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) |
#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) |
/* Processor specific flags for the Phdr p_flags field. */ |
#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ |
/* Processor specific values for the Shdr sh_type field. */ |
#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ |
#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ |
/* Processor specific flags for the Shdr sh_flags field. */ |
#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ |
#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ |
/* Processor specific values for the Dyn d_tag field. */ |
#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) |
#define DT_IA_64_NUM 1 |
/* IA-64 relocations. */ |
#define R_IA64_NONE 0x00 /* none */ |
#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ |
#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ |
#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ |
#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ |
#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ |
#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ |
#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ |
#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ |
#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ |
#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ |
#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ |
#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ |
#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ |
#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ |
#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ |
#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ |
#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ |
#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ |
#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ |
#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ |
#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ |
#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ |
#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ |
#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ |
#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ |
#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ |
#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ |
#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ |
#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ |
#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ |
#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ |
#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ |
#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ |
#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ |
#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ |
#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ |
#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ |
#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ |
#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ |
#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ |
#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ |
#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ |
#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ |
#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ |
#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ |
#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ |
#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ |
#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ |
#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ |
#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ |
#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ |
#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ |
#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ |
#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ |
#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ |
#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ |
#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ |
#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ |
#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ |
#define R_IA64_COPY 0x84 /* copy relocation */ |
#define R_IA64_SUB 0x85 /* Addend and symbol difference */ |
#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ |
#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ |
#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ |
#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ |
#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ |
#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ |
#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ |
#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ |
#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ |
#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ |
#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ |
#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ |
#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ |
#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ |
#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ |
#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ |
#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ |
#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ |
#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ |
/* SH specific declarations */ |
/* Processor specific flags for the ELF header e_flags field. */ |
#define EF_SH_MACH_MASK 0x1f |
#define EF_SH_UNKNOWN 0x0 |
#define EF_SH1 0x1 |
#define EF_SH2 0x2 |
#define EF_SH3 0x3 |
#define EF_SH_DSP 0x4 |
#define EF_SH3_DSP 0x5 |
#define EF_SH4AL_DSP 0x6 |
#define EF_SH3E 0x8 |
#define EF_SH4 0x9 |
#define EF_SH2E 0xb |
#define EF_SH4A 0xc |
#define EF_SH2A 0xd |
#define EF_SH4_NOFPU 0x10 |
#define EF_SH4A_NOFPU 0x11 |
#define EF_SH4_NOMMU_NOFPU 0x12 |
#define EF_SH2A_NOFPU 0x13 |
#define EF_SH3_NOMMU 0x14 |
#define EF_SH2A_SH4_NOFPU 0x15 |
#define EF_SH2A_SH3_NOFPU 0x16 |
#define EF_SH2A_SH4 0x17 |
#define EF_SH2A_SH3E 0x18 |
/* SH relocs. */ |
#define R_SH_NONE 0 |
#define R_SH_DIR32 1 |
#define R_SH_REL32 2 |
#define R_SH_DIR8WPN 3 |
#define R_SH_IND12W 4 |
#define R_SH_DIR8WPL 5 |
#define R_SH_DIR8WPZ 6 |
#define R_SH_DIR8BP 7 |
#define R_SH_DIR8W 8 |
#define R_SH_DIR8L 9 |
#define R_SH_SWITCH16 25 |
#define R_SH_SWITCH32 26 |
#define R_SH_USES 27 |
#define R_SH_COUNT 28 |
#define R_SH_ALIGN 29 |
#define R_SH_CODE 30 |
#define R_SH_DATA 31 |
#define R_SH_LABEL 32 |
#define R_SH_SWITCH8 33 |
#define R_SH_GNU_VTINHERIT 34 |
#define R_SH_GNU_VTENTRY 35 |
#define R_SH_TLS_GD_32 144 |
#define R_SH_TLS_LD_32 145 |
#define R_SH_TLS_LDO_32 146 |
#define R_SH_TLS_IE_32 147 |
#define R_SH_TLS_LE_32 148 |
#define R_SH_TLS_DTPMOD32 149 |
#define R_SH_TLS_DTPOFF32 150 |
#define R_SH_TLS_TPOFF32 151 |
#define R_SH_GOT32 160 |
#define R_SH_PLT32 161 |
#define R_SH_COPY 162 |
#define R_SH_GLOB_DAT 163 |
#define R_SH_JMP_SLOT 164 |
#define R_SH_RELATIVE 165 |
#define R_SH_GOTOFF 166 |
#define R_SH_GOTPC 167 |
/* Keep this the last entry. */ |
#define R_SH_NUM 256 |
/* S/390 specific definitions. */ |
/* Valid values for the e_flags field. */ |
#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ |
/* Additional s390 relocs */ |
#define R_390_NONE 0 /* No reloc. */ |
#define R_390_8 1 /* Direct 8 bit. */ |
#define R_390_12 2 /* Direct 12 bit. */ |
#define R_390_16 3 /* Direct 16 bit. */ |
#define R_390_32 4 /* Direct 32 bit. */ |
#define R_390_PC32 5 /* PC relative 32 bit. */ |
#define R_390_GOT12 6 /* 12 bit GOT offset. */ |
#define R_390_GOT32 7 /* 32 bit GOT offset. */ |
#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ |
#define R_390_COPY 9 /* Copy symbol at runtime. */ |
#define R_390_GLOB_DAT 10 /* Create GOT entry. */ |
#define R_390_JMP_SLOT 11 /* Create PLT entry. */ |
#define R_390_RELATIVE 12 /* Adjust by program base. */ |
#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ |
#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ |
#define R_390_GOT16 15 /* 16 bit GOT offset. */ |
#define R_390_PC16 16 /* PC relative 16 bit. */ |
#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ |
#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ |
#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ |
#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ |
#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ |
#define R_390_64 22 /* Direct 64 bit. */ |
#define R_390_PC64 23 /* PC relative 64 bit. */ |
#define R_390_GOT64 24 /* 64 bit GOT offset. */ |
#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ |
#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ |
#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ |
#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ |
#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ |
#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ |
#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ |
#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ |
#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ |
#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ |
#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ |
#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ |
#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ |
#define R_390_TLS_GDCALL 38 /* Tag for function call in general |
dynamic TLS code. */ |
#define R_390_TLS_LDCALL 39 /* Tag for function call in local |
dynamic TLS code. */ |
#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic |
thread local data. */ |
#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic |
thread local data. */ |
#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS |
block offset. */ |
#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS |
block offset. */ |
#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS |
block offset. */ |
#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic |
thread local data in LE code. */ |
#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic |
thread local data in LE code. */ |
#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for |
negated static TLS block offset. */ |
#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for |
negated static TLS block offset. */ |
#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for |
negated static TLS block offset. */ |
#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to |
static TLS block. */ |
#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to |
static TLS block. */ |
#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS |
block. */ |
#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS |
block. */ |
#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ |
#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ |
#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS |
block. */ |
#define R_390_20 57 /* Direct 20 bit. */ |
#define R_390_GOT20 58 /* 20 bit GOT offset. */ |
#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ |
#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS |
block offset. */ |
#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ |
/* Keep this the last entry. */ |
#define R_390_NUM 62 |
/* CRIS relocations. */ |
#define R_CRIS_NONE 0 |
#define R_CRIS_8 1 |
#define R_CRIS_16 2 |
#define R_CRIS_32 3 |
#define R_CRIS_8_PCREL 4 |
#define R_CRIS_16_PCREL 5 |
#define R_CRIS_32_PCREL 6 |
#define R_CRIS_GNU_VTINHERIT 7 |
#define R_CRIS_GNU_VTENTRY 8 |
#define R_CRIS_COPY 9 |
#define R_CRIS_GLOB_DAT 10 |
#define R_CRIS_JUMP_SLOT 11 |
#define R_CRIS_RELATIVE 12 |
#define R_CRIS_16_GOT 13 |
#define R_CRIS_32_GOT 14 |
#define R_CRIS_16_GOTPLT 15 |
#define R_CRIS_32_GOTPLT 16 |
#define R_CRIS_32_GOTREL 17 |
#define R_CRIS_32_PLT_GOTREL 18 |
#define R_CRIS_32_PLT_PCREL 19 |
#define R_CRIS_NUM 20 |
/* AMD x86-64 relocations. */ |
#define R_X86_64_NONE 0 /* No reloc */ |
#define R_X86_64_64 1 /* Direct 64 bit */ |
#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ |
#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ |
#define R_X86_64_PLT32 4 /* 32 bit PLT address */ |
#define R_X86_64_COPY 5 /* Copy symbol at runtime */ |
#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ |
#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ |
#define R_X86_64_RELATIVE 8 /* Adjust by program base */ |
#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative |
offset to GOT */ |
#define R_X86_64_32 10 /* Direct 32 bit zero extended */ |
#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ |
#define R_X86_64_16 12 /* Direct 16 bit zero extended */ |
#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ |
#define R_X86_64_8 14 /* Direct 8 bit sign extended */ |
#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ |
#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ |
#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ |
#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ |
#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset |
to two GOT entries for GD symbol */ |
#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset |
to two GOT entries for LD symbol */ |
#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ |
#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset |
to GOT entry for IE symbol */ |
#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ |
#define R_X86_64_PC64 24 /* PC relative 64 bit */ |
#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ |
#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative |
offset to GOT */ |
#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ |
#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset |
to GOT entry */ |
#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ |
#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ |
#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset |
to PLT entry */ |
#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ |
#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ |
#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ |
#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS |
descriptor. */ |
#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ |
#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ |
#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ |
#define R_X86_64_GOTPCRELX 41 /* like GOTPCREL, but optionally with |
linker optimizations */ |
#define R_X86_64_REX_GOTPCRELX 42 /* like GOTPCRELX, but a REX prefix |
is present */ |
#define R_X86_64_NUM 39 |
/* AM33 relocations. */ |
#define R_MN10300_NONE 0 /* No reloc. */ |
#define R_MN10300_32 1 /* Direct 32 bit. */ |
#define R_MN10300_16 2 /* Direct 16 bit. */ |
#define R_MN10300_8 3 /* Direct 8 bit. */ |
#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ |
#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ |
#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ |
#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ |
#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ |
#define R_MN10300_24 9 /* Direct 24 bit. */ |
#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ |
#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ |
#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ |
#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ |
#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ |
#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ |
#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ |
#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ |
#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ |
#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ |
#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ |
#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ |
#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ |
#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ |
#define R_MN10300_TLS_GD 24 /* 32-bit offset for global dynamic. */ |
#define R_MN10300_TLS_LD 25 /* 32-bit offset for local dynamic. */ |
#define R_MN10300_TLS_LDO 26 /* Module-relative offset. */ |
#define R_MN10300_TLS_GOTIE 27 /* GOT offset for static TLS block |
offset. */ |
#define R_MN10300_TLS_IE 28 /* GOT address for static TLS block |
offset. */ |
#define R_MN10300_TLS_LE 29 /* Offset relative to static TLS |
block. */ |
#define R_MN10300_TLS_DTPMOD 30 /* ID of module containing symbol. */ |
#define R_MN10300_TLS_DTPOFF 31 /* Offset in module TLS block. */ |
#define R_MN10300_TLS_TPOFF 32 /* Offset in static TLS block. */ |
#define R_MN10300_SYM_DIFF 33 /* Adjustment for next reloc as needed |
by linker relaxation. */ |
#define R_MN10300_ALIGN 34 /* Alignment requirement for linker |
relaxation. */ |
#define R_MN10300_NUM 35 |
/* M32R relocs. */ |
#define R_M32R_NONE 0 /* No reloc. */ |
#define R_M32R_16 1 /* Direct 16 bit. */ |
#define R_M32R_32 2 /* Direct 32 bit. */ |
#define R_M32R_24 3 /* Direct 24 bit. */ |
#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ |
#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ |
#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ |
#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ |
#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ |
#define R_M32R_LO16 9 /* Low 16 bit. */ |
#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ |
#define R_M32R_GNU_VTINHERIT 11 |
#define R_M32R_GNU_VTENTRY 12 |
/* M32R relocs use SHT_RELA. */ |
#define R_M32R_16_RELA 33 /* Direct 16 bit. */ |
#define R_M32R_32_RELA 34 /* Direct 32 bit. */ |
#define R_M32R_24_RELA 35 /* Direct 24 bit. */ |
#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ |
#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ |
#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ |
#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ |
#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ |
#define R_M32R_LO16_RELA 41 /* Low 16 bit */ |
#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ |
#define R_M32R_RELA_GNU_VTINHERIT 43 |
#define R_M32R_RELA_GNU_VTENTRY 44 |
#define R_M32R_REL32 45 /* PC relative 32 bit. */ |
#define R_M32R_GOT24 48 /* 24 bit GOT entry */ |
#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ |
#define R_M32R_COPY 50 /* Copy symbol at runtime */ |
#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ |
#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ |
#define R_M32R_RELATIVE 53 /* Adjust by program base */ |
#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ |
#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ |
#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned |
low */ |
#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed |
low */ |
#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ |
#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to |
GOT with unsigned low */ |
#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to |
GOT with signed low */ |
#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to |
GOT */ |
#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT |
with unsigned low */ |
#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT |
with signed low */ |
#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ |
#define R_M32R_NUM 256 /* Keep this the last entry. */ |
/* TILEPro relocations. */ |
#define R_TILEPRO_NONE 0 /* No reloc */ |
#define R_TILEPRO_32 1 /* Direct 32 bit */ |
#define R_TILEPRO_16 2 /* Direct 16 bit */ |
#define R_TILEPRO_8 3 /* Direct 8 bit */ |
#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */ |
#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */ |
#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */ |
#define R_TILEPRO_LO16 7 /* Low 16 bit */ |
#define R_TILEPRO_HI16 8 /* High 16 bit */ |
#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */ |
#define R_TILEPRO_COPY 10 /* Copy relocation */ |
#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */ |
#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */ |
#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */ |
#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */ |
#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */ |
#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */ |
#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */ |
#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */ |
#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */ |
#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */ |
#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */ |
#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */ |
#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */ |
#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */ |
#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */ |
#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */ |
#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */ |
#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */ |
#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */ |
#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */ |
#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */ |
#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */ |
#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */ |
#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */ |
#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */ |
#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */ |
#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */ |
#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */ |
#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */ |
#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */ |
#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */ |
#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */ |
#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */ |
#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */ |
#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */ |
#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */ |
#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */ |
#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */ |
#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */ |
#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */ |
#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */ |
#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */ |
#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */ |
#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */ |
#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */ |
/* Relocs 56-59 are currently not defined. */ |
#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */ |
#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */ |
#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */ |
#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */ |
#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */ |
#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */ |
#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */ |
#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */ |
#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */ |
#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */ |
#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */ |
#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */ |
#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */ |
#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */ |
#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */ |
#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */ |
#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */ |
#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */ |
#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */ |
#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ |
#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ |
#define R_TILEPRO_NUM 130 |
/* TILE-Gx relocations. */ |
#define R_TILEGX_NONE 0 /* No reloc */ |
#define R_TILEGX_64 1 /* Direct 64 bit */ |
#define R_TILEGX_32 2 /* Direct 32 bit */ |
#define R_TILEGX_16 3 /* Direct 16 bit */ |
#define R_TILEGX_8 4 /* Direct 8 bit */ |
#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */ |
#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */ |
#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */ |
#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */ |
#define R_TILEGX_HW0 9 /* hword 0 16-bit */ |
#define R_TILEGX_HW1 10 /* hword 1 16-bit */ |
#define R_TILEGX_HW2 11 /* hword 2 16-bit */ |
#define R_TILEGX_HW3 12 /* hword 3 16-bit */ |
#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */ |
#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */ |
#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */ |
#define R_TILEGX_COPY 16 /* Copy relocation */ |
#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */ |
#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */ |
#define R_TILEGX_RELATIVE 19 /* Adjust by program base */ |
#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */ |
#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */ |
#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */ |
#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */ |
#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */ |
#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */ |
#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */ |
#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */ |
#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */ |
#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */ |
#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */ |
#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */ |
#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */ |
#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */ |
#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */ |
#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */ |
#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */ |
#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */ |
#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */ |
#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */ |
#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */ |
#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */ |
#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */ |
#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */ |
#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */ |
#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */ |
#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */ |
#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */ |
#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */ |
#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */ |
#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */ |
#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */ |
#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */ |
#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */ |
#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */ |
#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */ |
#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */ |
#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */ |
#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */ |
#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */ |
#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */ |
#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */ |
#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */ |
#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */ |
#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */ |
#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */ |
#define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */ |
#define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */ |
#define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */ |
#define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */ |
#define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */ |
#define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */ |
#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */ |
#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */ |
#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */ |
#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */ |
#define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */ |
#define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */ |
#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */ |
#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */ |
#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */ |
#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */ |
#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */ |
#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */ |
#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */ |
#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */ |
#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */ |
#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */ |
#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */ |
#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */ |
/* Relocs 90-91 are currently not defined. */ |
#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */ |
#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */ |
#define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */ |
#define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */ |
#define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */ |
#define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */ |
#define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */ |
#define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */ |
#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */ |
#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */ |
#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */ |
#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */ |
/* Relocs 104-105 are currently not defined. */ |
#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */ |
#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */ |
#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */ |
#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */ |
#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */ |
#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */ |
#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */ |
#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */ |
#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */ |
#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */ |
#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */ |
#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */ |
#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */ |
#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */ |
#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */ |
#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */ |
#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ |
#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ |
#define R_TILEGX_NUM 130 |
#endif /* elf.h */ |
/programs/develop/ktcc/trunk/source/examples/ex1.c |
---|
0,0 → 1,8 |
#!/usr/local/bin/tcc -run |
#include <tcclib.h> |
int main() |
{ |
printf("Hello World\n"); |
return 0; |
} |
/programs/develop/ktcc/trunk/source/examples/ex2.c |
---|
0,0 → 1,98 |
#include <stdlib.h> |
#include <stdio.h> |
#define N 20 |
int nb_num; |
int tab[N]; |
int stack_ptr; |
int stack_op[N]; |
int stack_res[60]; |
int result; |
int find(int n, int i1, int a, int b, int op) |
{ |
int i, j; |
int c; |
if (stack_ptr >= 0) { |
stack_res[3*stack_ptr] = a; |
stack_op[stack_ptr] = op; |
stack_res[3*stack_ptr+1] = b; |
stack_res[3*stack_ptr+2] = n; |
if (n == result) |
return 1; |
tab[i1] = n; |
} |
for(i=0;i<nb_num;i++) { |
for(j=i+1;j<nb_num;j++) { |
a = tab[i]; |
b = tab[j]; |
if (a != 0 && b != 0) { |
tab[j] = 0; |
stack_ptr++; |
if (find(a + b, i, a, b, '+')) |
return 1; |
if (find(a - b, i, a, b, '-')) |
return 1; |
if (find(b - a, i, b, a, '-')) |
return 1; |
if (find(a * b, i, a, b, '*')) |
return 1; |
if (b != 0) { |
c = a / b; |
if (find(c, i, a, b, '/')) |
return 1; |
} |
if (a != 0) { |
c = b / a; |
if (find(c, i, b, a, '/')) |
return 1; |
} |
stack_ptr--; |
tab[i] = a; |
tab[j] = b; |
} |
} |
} |
return 0; |
} |
int main(int argc, char **argv) |
{ |
int i, res, p; |
if (argc < 3) { |
printf("usage: %s: result numbers...\n" |
"Try to find result from numbers with the 4 basic operations.\n", argv[0]); |
exit(1); |
} |
p = 1; |
result = atoi(argv[p]); |
printf("result=%d\n", result); |
nb_num = 0; |
for(i=p+1;i<argc;i++) { |
tab[nb_num++] = atoi(argv[i]); |
} |
stack_ptr = -1; |
res = find(0, 0, 0, 0, ' '); |
if (res) { |
for(i=0;i<=stack_ptr;i++) { |
printf("%d %c %d = %d\n", |
stack_res[3*i], stack_op[i], |
stack_res[3*i+1], stack_res[3*i+2]); |
} |
return 0; |
} else { |
printf("Impossible\n"); |
return 1; |
} |
} |
/programs/develop/ktcc/trunk/source/examples/ex3.c |
---|
0,0 → 1,24 |
#include <stdlib.h> |
#include <stdio.h> |
int fib(n) |
{ |
if (n <= 2) |
return 1; |
else |
return fib(n-1) + fib(n-2); |
} |
int main(int argc, char **argv) |
{ |
int n; |
if (argc < 2) { |
printf("usage: fib n\n" |
"Compute nth Fibonacci number\n"); |
return 1; |
} |
n = atoi(argv[1]); |
printf("fib(%d) = %d\n", n, fib(n, 2)); |
return 0; |
} |
/programs/develop/ktcc/trunk/source/examples/ex4.c |
---|
0,0 → 1,26 |
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 |
#include <stdlib.h> |
#include <stdio.h> |
#include <X11/Xlib.h> |
/* Yes, TCC can use X11 too ! */ |
int main(int argc, char **argv) |
{ |
Display *display; |
Screen *screen; |
display = XOpenDisplay(""); |
if (!display) { |
fprintf(stderr, "Could not open X11 display\n"); |
exit(1); |
} |
printf("X11 display opened.\n"); |
screen = XScreenOfDisplay(display, 0); |
printf("width = %d\nheight = %d\ndepth = %d\n", |
screen->width, |
screen->height, |
screen->root_depth); |
XCloseDisplay(display); |
return 0; |
} |
/programs/develop/ktcc/trunk/source/examples/ex5.c |
---|
0,0 → 1,8 |
#include <stdlib.h> |
#include <stdio.h> |
int main() |
{ |
printf("Hello World\n"); |
return 0; |
} |
/programs/develop/ktcc/trunk/source/i386-asm.c |
---|
2,6 → 2,7 |
* i386 specific functions for TCC assembler |
* |
* Copyright (c) 2001, 2002 Fabrice Bellard |
* Copyright (c) 2009 Frédéric Feret (x86_64 support) |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
18,14 → 19,18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
#include "tcc.h" |
/* #define NB_ASM_REGS 8 */ |
#define MAX_OPERANDS 3 |
#define NB_SAVED_REGS 3 |
typedef struct ASMInstr { |
uint16_t sym; |
uint16_t opcode; |
uint16_t instr_type; |
#define TOK_ASM_first TOK_ASM_clc |
#define TOK_ASM_last TOK_ASM_emms |
#define TOK_ASM_alllast TOK_ASM_pxor |
#define OPC_JMP 0x01 /* jmp operand */ |
#define OPC_B 0x02 /* only used zith OPC_WL */ |
#define OPC_B 0x02 /* only used with OPC_WL */ |
#define OPC_WL 0x04 /* accepts w, l or no suffix */ |
#define OPC_BWL (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */ |
#define OPC_REG 0x08 /* register is added to opcode */ |
37,47 → 42,58 |
#define OPC_ARITH 0x0200 /* arithmetic opcodes */ |
#define OPC_SHORTJMP 0x0400 /* short jmp operand */ |
#define OPC_FARITH 0x0800 /* FPU arithmetic opcodes */ |
#ifdef TCC_TARGET_X86_64 |
# define OPC_WLQ 0x1000 /* accepts w, l, q or no suffix */ |
# define OPC_BWLQ (OPC_B | OPC_WLQ) /* accepts b, w, l, q or no suffix */ |
# define OPC_WLX OPC_WLQ |
#else |
# define OPC_WLX OPC_WL |
#endif |
#define OPC_GROUP_SHIFT 13 |
/* in order to compress the operand type, we use specific operands and |
we or only with EA */ |
#define OPT_REG8 0 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_MMX 3 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_SSE 4 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_CR 5 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_TR 6 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_DB 7 /* warning: value is hardcoded from TOK_ASM_xxx */ |
#define OPT_SEG 8 |
#define OPT_ST 9 |
#define OPT_IM8 10 |
#define OPT_IM8S 11 |
#define OPT_IM16 12 |
#define OPT_IM32 13 |
#define OPT_EAX 14 /* %al, %ax or %eax register */ |
#define OPT_ST0 15 /* %st(0) register */ |
#define OPT_CL 16 /* %cl register */ |
#define OPT_DX 17 /* %dx register */ |
#define OPT_ADDR 18 /* OP_EA with only offset */ |
#define OPT_INDIR 19 /* *(expr) */ |
enum { |
OPT_REG8=0, /* warning: value is hardcoded from TOK_ASM_xxx */ |
OPT_REG16, /* warning: value is hardcoded from TOK_ASM_xxx */ |
OPT_REG32, /* warning: value is hardcoded from TOK_ASM_xxx */ |
#ifdef TCC_TARGET_X86_64 |
OPT_REG64, /* warning: value is hardcoded from TOK_ASM_xxx */ |
#endif |
OPT_MMX, /* warning: value is hardcoded from TOK_ASM_xxx */ |
OPT_SSE, /* warning: value is hardcoded from TOK_ASM_xxx */ |
OPT_CR, /* warning: value is hardcoded from TOK_ASM_xxx */ |
OPT_TR, /* warning: value is hardcoded from TOK_ASM_xxx */ |
OPT_DB, /* warning: value is hardcoded from TOK_ASM_xxx */ |
OPT_SEG, |
OPT_ST, |
OPT_IM8, |
OPT_IM8S, |
OPT_IM16, |
OPT_IM32, |
#ifdef TCC_TARGET_X86_64 |
OPT_IM64, |
#endif |
OPT_EAX, /* %al, %ax, %eax or %rax register */ |
OPT_ST0, /* %st(0) register */ |
OPT_CL, /* %cl register */ |
OPT_DX, /* %dx register */ |
OPT_ADDR, /* OP_EA with only offset */ |
OPT_INDIR, /* *(expr) */ |
/* composite types */ |
#define OPT_COMPOSITE_FIRST 20 |
#define OPT_IM 20 /* IM8 | IM16 | IM32 */ |
#define OPT_REG 21 /* REG8 | REG16 | REG32 */ |
#define OPT_REGW 22 /* REG16 | REG32 */ |
#define OPT_IMW 23 /* IM16 | IM32 */ |
OPT_COMPOSITE_FIRST, |
OPT_IM, /* IM8 | IM16 | IM32 | IM64 */ |
OPT_REG, /* REG8 | REG16 | REG32 | REG64 */ |
OPT_REGW, /* REG16 | REG32 | REG64 */ |
OPT_IMW, /* IM16 | IM32 | IM64 */ |
#ifdef TCC_TARGET_X86_64 |
OPT_IMNO64, /* IM16 | IM32 */ |
#endif |
/* can be ored with any OPT_xxx */ |
#define OPT_EA 0x80 |
OPT_EA = 0x80 |
}; |
uint8_t nb_ops; |
uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */ |
} ASMInstr; |
typedef struct Operand { |
uint32_t type; |
#define OP_REG8 (1 << OPT_REG8) |
#define OP_REG16 (1 << OPT_REG16) |
#define OP_REG32 (1 << OPT_REG32) |
98,10 → 114,39 |
#define OP_DX (1 << OPT_DX) |
#define OP_ADDR (1 << OPT_ADDR) |
#define OP_INDIR (1 << OPT_INDIR) |
#ifdef TCC_TARGET_X86_64 |
# define OP_REG64 (1 << OPT_REG64) |
# define OP_IM64 (1 << OPT_IM64) |
#else |
# define OP_REG64 0 |
# define OP_IM64 0 |
#endif |
#define OP_EA 0x40000000 |
#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32) |
#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64) |
#ifdef TCC_TARGET_X86_64 |
# define OP_IM OP_IM64 |
# define TREG_XAX TREG_RAX |
# define TREG_XCX TREG_RCX |
# define TREG_XDX TREG_RDX |
#else |
#define OP_IM OP_IM32 |
# define TREG_XAX TREG_EAX |
# define TREG_XCX TREG_ECX |
# define TREG_XDX TREG_EDX |
#endif |
typedef struct ASMInstr { |
uint16_t sym; |
uint16_t opcode; |
uint16_t instr_type; |
uint8_t nb_ops; |
uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */ |
} ASMInstr; |
typedef struct Operand { |
uint32_t type; |
int8_t reg; /* register, -1 if none */ |
int8_t reg2; /* second register, -1 if none */ |
uint8_t shift; |
108,14 → 153,18 |
ExprValue e; |
} Operand; |
static const uint8_t reg_to_size[5] = { |
static const uint8_t reg_to_size[9] = { |
/* |
[OP_REG8] = 0, |
[OP_REG16] = 1, |
[OP_REG32] = 2, |
#ifdef TCC_TARGET_X86_64 |
[OP_REG64] = 3, |
#endif |
*/ |
0, 0, 1, 0, 2, 0, 0, 0, 3 |
}; |
#define WORD_PREFIX_OPCODE 0x66 |
#define NB_TEST_OPCODES 30 |
static const uint8_t test_bits[NB_TEST_OPCODES] = { |
151,6 → 200,15 |
0x0f, /* g */ |
}; |
static const uint8_t segment_prefixes[] = { |
0x26, /* es */ |
0x2e, /* cs */ |
0x36, /* ss */ |
0x3e, /* ds */ |
0x64, /* fs */ |
0x65 /* gs */ |
}; |
static const ASMInstr asm_instrs[] = { |
#define ALT(x) x |
#define DEF_ASM_OP0(name, opcode) |
158,8 → 216,11 |
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }}, |
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }}, |
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 3, { op0, op1, op2 }}, |
#ifdef TCC_TARGET_X86_64 |
# include "x86_64-asm.h" |
#else |
#include "i386-asm.h" |
#endif |
/* last operation */ |
{ 0, }, |
}; |
171,13 → 232,20 |
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) |
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) |
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) |
#ifdef TCC_TARGET_X86_64 |
# include "x86_64-asm.h" |
#else |
#include "i386-asm.h" |
#endif |
}; |
static inline int get_reg_shift(TCCState *s1) |
{ |
int shift, v; |
#ifdef I386_ASM_16 |
if (s1->seg_size == 16) |
tcc_error("invalid effective address"); |
#endif |
v = asm_int_expr(s1); |
switch(v) { |
case 1: |
202,19 → 270,26 |
static int asm_parse_reg(void) |
{ |
int reg; |
int reg = 0; |
if (tok != '%') |
goto error_32; |
next(); |
if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) { |
reg = tok - TOK_ASM_eax; |
next(); |
return reg; |
#ifdef TCC_TARGET_X86_64 |
} else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) { |
reg = tok - TOK_ASM_rax; |
#endif |
#ifdef I386_ASM_16 |
} else if (tok >= TOK_ASM_ax && tok <= TOK_ASM_di) { |
reg = tok - TOK_ASM_ax; |
#endif |
} else { |
error_32: |
expect("32 bit register"); |
return 0; |
expect("register"); |
} |
next(); |
return reg; |
} |
static void parse_operand(TCCState *s1, Operand *op) |
235,11 → 310,11 |
reg = tok - TOK_ASM_al; |
op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */ |
op->reg = reg & 7; |
if ((op->type & OP_REG) && op->reg == TREG_EAX) |
if ((op->type & OP_REG) && op->reg == TREG_XAX) |
op->type |= OP_EAX; |
else if (op->type == OP_REG8 && op->reg == TREG_ECX) |
else if (op->type == OP_REG8 && op->reg == TREG_XCX) |
op->type |= OP_CL; |
else if (op->type == OP_REG16 && op->reg == TREG_EDX) |
else if (op->type == OP_REG16 && op->reg == TREG_XDX) |
op->type |= OP_DX; |
} else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) { |
op->type = OP_DB; |
255,7 → 330,7 |
next(); |
if (tok != TOK_PPNUM) |
goto reg_error; |
p = tokc.cstr->data; |
p = tokc.str.data; |
reg = p[0] - '0'; |
if ((unsigned)reg >= 8 || p[1] != '\0') |
goto reg_error; |
268,7 → 343,7 |
goto no_skip; |
} else { |
reg_error: |
error("unknown register"); |
tcc_error("unknown register"); |
} |
next(); |
no_skip: ; |
276,7 → 351,7 |
/* constant value */ |
next(); |
asm_expr(s1, &e); |
op->type = OP_IM32; |
op->type = OP_IM; |
op->e.v = e.v; |
op->e.sym = e.sym; |
if (!op->e.sym) { |
286,6 → 361,10 |
op->type |= OP_IM8S; |
if (op->e.v == (uint16_t)op->e.v) |
op->type |= OP_IM16; |
#ifdef TCC_TARGET_X86_64 |
if (op->e.v == (uint32_t)op->e.v) |
op->type |= OP_IM32; |
#endif |
} |
} else { |
/* address(reg,reg2,shift) with all variants */ |
298,9 → 377,21 |
op->e.v = e.v; |
op->e.sym = e.sym; |
} else { |
next(); |
if (tok == '%') { |
unget_tok('('); |
op->e.v = 0; |
op->e.sym = NULL; |
} else { |
/* bracketed offset expression */ |
asm_expr(s1, &e); |
if (tok != ')') |
expect(")"); |
next(); |
op->e.v = e.v; |
op->e.sym = e.sym; |
} |
} |
if (tok == '(') { |
next(); |
if (tok != ',') { |
311,9 → 402,11 |
if (tok != ',') { |
op->reg2 = asm_parse_reg(); |
} |
skip(','); |
if (tok == ',') { |
next(); |
op->shift = get_reg_shift(s1); |
} |
} |
skip(')'); |
} |
if (op->reg == -1 && op->reg2 == -1) |
323,16 → 416,46 |
} |
/* XXX: unify with C code output ? */ |
static void gen_expr32(ExprValue *pe) |
ST_FUNC void gen_expr32(ExprValue *pe) |
{ |
if (pe->sym) |
greloc(cur_text_section, pe->sym, ind, R_386_32); |
gen_le32(pe->v); |
gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v); |
} |
#ifdef TCC_TARGET_X86_64 |
static void gen_expr64(ExprValue *pe) |
{ |
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v); |
} |
#endif |
/* XXX: unify with C code output ? */ |
static void gen_disp32(ExprValue *pe) |
{ |
Sym *sym = pe->sym; |
if (sym && sym->r == cur_text_section->sh_num) { |
/* same section: we can output an absolute value. Note |
that the TCC compiler behaves differently here because |
it always outputs a relocation to ease (future) code |
elimination in the linker */ |
gen_le32(pe->v + sym->jnext - ind - 4); |
} else { |
if (sym && sym->type.t == VT_VOID) { |
sym->type.t = VT_FUNC; |
sym->type.ref = NULL; |
} |
gen_addrpc32(VT_SYM, sym, pe->v); |
} |
} |
#ifdef I386_ASM_16 |
static void gen_expr16(ExprValue *pe) |
{ |
if (pe->sym) |
greloc(cur_text_section, pe->sym, ind, R_386_16); |
gen_le16(pe->v); |
} |
static void gen_disp16(ExprValue *pe) |
{ |
Sym *sym; |
sym = pe->sym; |
if (sym) { |
341,26 → 464,20 |
that the TCC compiler behaves differently here because |
it always outputs a relocation to ease (future) code |
elimination in the linker */ |
gen_le32(pe->v + (long)sym->next - ind - 4); |
gen_le16(pe->v + sym->jnext - ind - 2); |
} else { |
greloc(cur_text_section, sym, ind, R_386_PC32); |
gen_le32(pe->v - 4); |
greloc(cur_text_section, sym, ind, R_386_PC16); |
gen_le16(pe->v - 2); |
} |
} else { |
/* put an empty PC32 relocation */ |
put_elf_reloc(symtab_section, cur_text_section, |
ind, R_386_PC32, 0); |
gen_le32(pe->v - 4); |
ind, R_386_PC16, 0); |
gen_le16(pe->v - 2); |
} |
} |
#endif |
static void gen_le16(int v) |
{ |
g(v); |
g(v >> 8); |
} |
/* generate the modrm operand */ |
static inline void asm_modrm(int reg, Operand *op) |
{ |
370,8 → 487,16 |
g(0xc0 + (reg << 3) + op->reg); |
} else if (op->reg == -1 && op->reg2 == -1) { |
/* displacement only */ |
#ifdef I386_ASM_16 |
if (tcc_state->seg_size == 16) { |
g(0x06 + (reg << 3)); |
gen_expr16(&op->e); |
} else if (tcc_state->seg_size == 32) |
#endif |
{ |
g(0x05 + (reg << 3)); |
gen_expr32(&op->e); |
} |
} else { |
sib_reg1 = op->reg; |
/* fist compute displacement encoding */ |
389,6 → 514,9 |
reg1 = op->reg; |
if (op->reg2 != -1) |
reg1 = 4; |
#ifdef I386_ASM_16 |
if (tcc_state->seg_size == 32) { |
#endif |
g(mod + (reg << 3) + reg1); |
if (reg1 == 4) { |
/* add sib byte */ |
397,34 → 525,96 |
reg2 = 4; /* indicate no index */ |
g((op->shift << 6) + (reg2 << 3) + sib_reg1); |
} |
#ifdef I386_ASM_16 |
} else if (tcc_state->seg_size == 16) { |
/* edi = 7, esi = 6 --> di = 5, si = 4 */ |
if ((reg1 == 6) || (reg1 == 7)) { |
reg1 -= 2; |
/* ebx = 3 --> bx = 7 */ |
} else if (reg1 == 3) { |
reg1 = 7; |
/* o32 = 5 --> o16 = 6 */ |
} else if (reg1 == 5) { |
reg1 = 6; |
/* sib not valid in 16-bit mode */ |
} else if (reg1 == 4) { |
reg2 = op->reg2; |
/* bp + si + offset */ |
if ((sib_reg1 == 5) && (reg2 == 6)) { |
reg1 = 2; |
/* bp + di + offset */ |
} else if ((sib_reg1 == 5) && (reg2 == 7)) { |
reg1 = 3; |
/* bx + si + offset */ |
} else if ((sib_reg1 == 3) && (reg2 == 6)) { |
reg1 = 0; |
/* bx + di + offset */ |
} else if ((sib_reg1 == 3) && (reg2 == 7)) { |
reg1 = 1; |
} else { |
tcc_error("invalid effective address"); |
} |
if (op->e.v == 0) |
mod = 0; |
} else { |
tcc_error("invalid register"); |
} |
g(mod + (reg << 3) + reg1); |
} |
#endif |
/* add offset */ |
if (mod == 0x40) { |
g(op->e.v); |
} else if (mod == 0x80 || op->reg == -1) { |
#ifdef I386_ASM_16 |
if (tcc_state->seg_size == 16) |
gen_expr16(&op->e); |
else if (tcc_state->seg_size == 32) |
#endif |
gen_expr32(&op->e); |
} |
} |
} |
static void asm_opcode(TCCState *s1, int opcode) |
ST_FUNC void asm_opcode(TCCState *s1, int opcode) |
{ |
const ASMInstr *pa; |
int i, modrm_index, reg, v, op1, is_short_jmp; |
int nb_ops, s, ss; |
int i, modrm_index, reg, v, op1, is_short_jmp, seg_prefix; |
int nb_ops, s; |
Operand ops[MAX_OPERANDS], *pop; |
int op_type[3]; /* decoded op type */ |
#ifdef I386_ASM_16 |
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; |
seg_prefix = 0; |
for(;;) { |
if (tok == ';' || tok == TOK_LINEFEED) |
break; |
if (nb_ops >= MAX_OPERANDS) { |
error("incorrect number of operands"); |
tcc_error("incorrect number of operands"); |
} |
parse_operand(s1, pop); |
if (tok == ':') { |
if (pop->type != OP_SEG || seg_prefix) |
tcc_error("incorrect prefix"); |
seg_prefix = segment_prefixes[pop->reg]; |
next(); |
parse_operand(s1, pop); |
#ifndef I386_ASM_16 |
if (!(pop->type & OP_EA)) { |
tcc_error("segment prefix must be followed by memory reference"); |
} |
#endif |
} |
pop++; |
nb_ops++; |
if (tok != ',') |
444,23 → 634,22 |
if (!((unsigned)v < 8 * 6 && (v % 6) == 0)) |
continue; |
} else if (pa->instr_type & OPC_ARITH) { |
if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4)) |
if (!(opcode >= pa->sym && opcode < pa->sym + 8*NBWLX)) |
continue; |
goto compute_size; |
s = (opcode - pa->sym) % NBWLX; |
} else if (pa->instr_type & OPC_SHIFT) { |
if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4)) |
if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX)) |
continue; |
goto compute_size; |
s = (opcode - pa->sym) % NBWLX; |
} else if (pa->instr_type & OPC_TEST) { |
if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES)) |
continue; |
} else if (pa->instr_type & OPC_B) { |
if (!(opcode >= pa->sym && opcode <= pa->sym + 3)) |
if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX)) |
continue; |
compute_size: |
s = (opcode - pa->sym) & 3; |
} else if (pa->instr_type & OPC_WL) { |
if (!(opcode >= pa->sym && opcode <= pa->sym + 2)) |
s = opcode - pa->sym; |
} else if (pa->instr_type & OPC_WLX) { |
if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX-1)) |
continue; |
s = opcode - pa->sym + 1; |
} else { |
476,17 → 665,22 |
op2 = op1 & 0x1f; |
switch(op2) { |
case OPT_IM: |
v = OP_IM8 | OP_IM16 | OP_IM32; |
v = OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64; |
break; |
case OPT_REG: |
v = OP_REG8 | OP_REG16 | OP_REG32; |
v = OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64; |
break; |
case OPT_REGW: |
v = OP_REG16 | OP_REG32; |
v = OP_REG16 | OP_REG32 | OP_REG64; |
break; |
case OPT_IMW: |
v = OP_IM16 | OP_IM32 | OP_IM64; |
break; |
#ifdef TCC_TARGET_X86_64 |
case OPT_IMNO64: |
v = OP_IM16 | OP_IM32; |
break; |
#endif |
default: |
v = 1 << op2; |
break; |
502,48 → 696,105 |
next: ; |
} |
if (pa->sym == 0) { |
if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) { |
if (opcode >= TOK_ASM_first && opcode <= TOK_ASM_last) { |
int b; |
b = op0_codes[opcode - TOK_ASM_pusha]; |
b = op0_codes[opcode - TOK_ASM_first]; |
#ifdef I386_ASM_16 |
if (opcode == TOK_ASM_o32) { |
if (s1->seg_size == 32) |
tcc_error("incorrect prefix"); |
else |
o32 = data32 = 1; |
} else if (opcode == TOK_ASM_a32) { |
if (s1->seg_size == 32) |
tcc_error("incorrect prefix"); |
else |
a32 = addr32 = 1; |
} |
#endif |
if (b & 0xff00) |
g(b >> 8); |
g(b); |
return; |
} else if (opcode <= TOK_ASM_alllast) { |
tcc_error("bad operand with opcode '%s'", |
get_tok_str(opcode, NULL)); |
} else { |
error("unknown opcode '%s'", |
tcc_error("unknown opcode '%s'", |
get_tok_str(opcode, NULL)); |
} |
} |
/* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */ |
if (s == 3) { |
for(i = 0; s == 3 && i < nb_ops; i++) { |
if (s == NBWLX-1) { |
for(i = 0; s == NBWLX-1 && i < nb_ops; i++) { |
if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX))) |
s = reg_to_size[ops[i].type & OP_REG]; |
} |
if (s == 3) { |
if (s == NBWLX-1) { |
if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) && |
(ops[0].type & (OP_SEG | OP_IM8S | OP_IM32))) |
(ops[0].type & (OP_SEG | OP_IM8S | OP_IM32 | OP_IM64))) |
s = 2; |
else |
error("cannot infer opcode suffix"); |
tcc_error("cannot infer opcode suffix"); |
} |
} |
#ifdef I386_ASM_16 |
for(i = 0; i < nb_ops; i++) { |
if (ops[i].type & OP_REG32) { |
if (s1->seg_size == 16) |
o32 = 1; |
} else if (!(ops[i].type & OP_REG32)) { |
if (s1->seg_size == 32) |
o32 = 1; |
} |
} |
if (s == 1 || (pa->instr_type & OPC_D16)) { |
if (s1->seg_size == 32) |
o32 = 1; |
} else if (s == 2) { |
if (s1->seg_size == 16) { |
if (!(pa->instr_type & OPC_D16)) |
o32 = 1; |
} |
} |
/* generate a16/a32 prefix if needed */ |
if ((a32 == 1) && (addr32 == 0)) |
g(0x67); |
/* generate o16/o32 prefix if needed */ |
if ((o32 == 1) && (data32 == 0)) |
g(0x66); |
addr32 = data32 = 0; |
#else |
/* generate data16 prefix if needed */ |
ss = s; |
if (s == 1 || (pa->instr_type & OPC_D16)) |
g(WORD_PREFIX_OPCODE); |
else if (s == 2) |
s = 1; |
g(0x66); |
#ifdef TCC_TARGET_X86_64 |
else if (s == 3) { |
/* generate REX prefix */ |
if ((opcode != TOK_ASM_push && opcode != TOK_ASM_pop) |
|| !(ops[0].type & OP_REG64)) |
g(0x48); |
} |
#endif |
#endif |
/* now generates the operation */ |
if (pa->instr_type & OPC_FWAIT) |
g(0x9b); |
if (seg_prefix) |
g(seg_prefix); |
v = pa->opcode; |
if (v == 0x69 || v == 0x69) { |
if ((v == 0x69 || v == 0x6b) && nb_ops == 2) { |
/* kludge for imul $im, %reg */ |
nb_ops = 3; |
ops[2] = ops[1]; |
op_type[2] = op_type[1]; |
} else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) { |
v--; /* int $3 case */ |
nb_ops = 0; |
557,7 → 808,7 |
nb_ops = 0; |
} else if (v <= 0x05) { |
/* arith case */ |
v += ((opcode - TOK_ASM_addb) >> 2) << 3; |
v += ((opcode - TOK_ASM_addb) / NBWLX) << 3; |
} else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) { |
/* fpu arith case */ |
v += ((opcode - pa->sym) / 6) << 3; |
574,7 → 825,7 |
v += 7; |
} |
if (pa->instr_type & OPC_B) |
v += s; |
v += s >= 1; |
if (pa->instr_type & OPC_TEST) |
v += test_bits[opcode - pa->sym]; |
if (pa->instr_type & OPC_SHORTJMP) { |
587,7 → 838,7 |
goto no_short_jump; |
if (sym->r != cur_text_section->sh_num) |
goto no_short_jump; |
jmp_disp = ops[0].e.v + (long)sym->next - ind - 2; |
jmp_disp = ops[0].e.v + sym->jnext - ind - 2; |
if (jmp_disp == (int8_t)jmp_disp) { |
/* OK to generate jump */ |
is_short_jmp = 1; |
602,7 → 853,7 |
else |
v += 0x0f10; |
} else { |
error("invalid displacement"); |
tcc_error("invalid displacement"); |
} |
} |
} |
614,11 → 865,11 |
/* search which operand will used for modrm */ |
modrm_index = 0; |
if (pa->instr_type & OPC_SHIFT) { |
reg = (opcode - pa->sym) >> 2; |
reg = (opcode - pa->sym) / NBWLX; |
if (reg == 6) |
reg = 7; |
} else if (pa->instr_type & OPC_ARITH) { |
reg = (opcode - pa->sym) >> 2; |
reg = (opcode - pa->sym) / NBWLX; |
} else if (pa->instr_type & OPC_FARITH) { |
reg = (opcode - pa->sym) / 6; |
} else { |
636,7 → 887,7 |
goto modrm_found; |
} |
#ifdef ASM_DEBUG |
error("bad op table"); |
tcc_error("bad op table"); |
#endif |
modrm_found: |
modrm_index = i; |
655,26 → 906,35 |
} |
/* emit constants */ |
#ifndef TCC_TARGET_X86_64 |
if (pa->opcode == 0x9a || pa->opcode == 0xea) { |
/* ljmp or lcall kludge */ |
#ifdef I386_ASM_16 |
if (s1->seg_size == 16 && o32 == 0) |
gen_expr16(&ops[1].e); |
else |
#endif |
gen_expr32(&ops[1].e); |
if (ops[0].e.sym) |
error("cannot relocate"); |
tcc_error("cannot relocate"); |
gen_le16(ops[0].e.v); |
} else { |
return; |
} |
#endif |
for(i = 0;i < nb_ops; i++) { |
v = op_type[i]; |
if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) { |
if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64 | OP_IM8S | OP_ADDR)) { |
/* if multiple sizes are given it means we must look |
at the op size */ |
if (v == (OP_IM8 | OP_IM16 | OP_IM32) || |
v == (OP_IM16 | OP_IM32)) { |
if (ss == 0) |
if ((v | OP_IM8 | OP_IM64) == (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64)) { |
if (s == 0) |
v = OP_IM8; |
else if (ss == 1) |
else if (s == 1) |
v = OP_IM16; |
else if (s == 2 || (v & OP_IM64) == 0) |
v = OP_IM32; |
else |
v = OP_IM32; |
v = OP_IM64; |
} |
if (v & (OP_IM8 | OP_IM8S)) { |
if (ops[i].e.sym) |
681,29 → 941,61 |
goto error_relocate; |
g(ops[i].e.v); |
} else if (v & OP_IM16) { |
if (ops[i].e.sym) { |
#ifdef I386_ASM_16 |
if (s1->seg_size == 16) |
gen_expr16(&ops[i].e); |
else |
#endif |
if (ops[i].e.sym) |
error_relocate: |
error("cannot relocate"); |
} |
tcc_error("cannot relocate"); |
else |
gen_le16(ops[i].e.v); |
} else { |
if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { |
if (is_short_jmp) |
g(ops[i].e.v); |
#ifdef I386_ASM_16 |
else if (s1->seg_size == 16) |
gen_disp16(&ops[i].e); |
#endif |
else |
gen_disp32(&ops[i].e); |
} else { |
#ifdef I386_ASM_16 |
if (s1->seg_size == 16 && !((o32 == 1) && (v & OP_IM32))) |
gen_expr16(&ops[i].e); |
else |
#endif |
#ifdef TCC_TARGET_X86_64 |
if (v & OP_IM64) |
gen_expr64(&ops[i].e); |
else |
#endif |
gen_expr32(&ops[i].e); |
} |
} |
#ifdef I386_ASM_16 |
} else if (v & (OP_REG16 | OP_REG32)) { |
if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { |
/* jmp $r */ |
g(0xE0 + ops[i].reg); |
} |
#endif |
#ifdef TCC_TARGET_X86_64 |
} else if (v & (OP_REG32 | OP_REG64)) { |
if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { |
/* jmp $r */ |
g(0xE0 + ops[i].reg); |
} |
#endif |
} |
} |
#ifdef I386_ASM_16 |
a32 = o32 = 0; |
#endif |
} |
#define NB_SAVED_REGS 3 |
#define NB_ASM_REGS 8 |
/* return the constraint priority (we allocate first the lowest |
numbered constraints) */ |
static inline int constraint_priority(const char *str) |
744,7 → 1036,7 |
pr = 4; |
break; |
default: |
error("unknown constraint '%c'", c); |
tcc_error("unknown constraint '%c'", c); |
pr = 0; |
} |
if (pr > priority) |
765,7 → 1057,7 |
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask) |
static void asm_compute_constraints(ASMOperand *operands, |
ST_FUNC void asm_compute_constraints(ASMOperand *operands, |
int nb_operands, int nb_outputs, |
const uint8_t *clobber_regs, |
int *pout_reg) |
795,11 → 1087,11 |
/* this is a reference to another constraint */ |
k = find_constraint(operands, nb_operands, str, NULL); |
if ((unsigned)k >= i || i < nb_outputs) |
error("invalid reference in constraint %d ('%s')", |
tcc_error("invalid reference in constraint %d ('%s')", |
i, str); |
op->ref_index = k; |
if (operands[k].input_index >= 0) |
error("cannot reference twice the same operand"); |
tcc_error("cannot reference twice the same operand"); |
operands[k].input_index = i; |
op->priority = 5; |
} else { |
859,30 → 1151,30 |
/* FALL THRU */ |
case '&': |
if (j >= nb_outputs) |
error("'%c' modifier can only be applied to outputs", c); |
tcc_error("'%c' modifier can only be applied to outputs", c); |
reg_mask = REG_IN_MASK | REG_OUT_MASK; |
goto try_next; |
case 'A': |
/* allocate both eax and edx */ |
if (is_reg_allocated(TREG_EAX) || |
is_reg_allocated(TREG_EDX)) |
if (is_reg_allocated(TREG_XAX) || |
is_reg_allocated(TREG_XDX)) |
goto try_next; |
op->is_llong = 1; |
op->reg = TREG_EAX; |
regs_allocated[TREG_EAX] |= reg_mask; |
regs_allocated[TREG_EDX] |= reg_mask; |
op->reg = TREG_XAX; |
regs_allocated[TREG_XAX] |= reg_mask; |
regs_allocated[TREG_XDX] |= reg_mask; |
break; |
case 'a': |
reg = TREG_EAX; |
reg = TREG_XAX; |
goto alloc_reg; |
case 'b': |
reg = 3; |
goto alloc_reg; |
case 'c': |
reg = TREG_ECX; |
reg = TREG_XCX; |
goto alloc_reg; |
case 'd': |
reg = TREG_EDX; |
reg = TREG_XDX; |
goto alloc_reg; |
case 'S': |
reg = 6; |
950,7 → 1242,7 |
} |
break; |
default: |
error("asm constraint %d ('%s') could not be satisfied", |
tcc_error("asm constraint %d ('%s') could not be satisfied", |
j, op->constraint); |
break; |
} |
973,7 → 1265,7 |
if (!(regs_allocated[reg] & REG_OUT_MASK)) |
goto reg_found2; |
} |
error("could not find free output register for reloading"); |
tcc_error("could not find free output register for reloading"); |
reg_found2: |
*pout_reg = reg; |
break; |
997,7 → 1289,7 |
#endif |
} |
static void subst_asm_operand(CString *add_str, |
ST_FUNC void subst_asm_operand(CString *add_str, |
SValue *sv, int modifier) |
{ |
int r, reg, size, val; |
1008,8 → 1300,8 |
if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n') |
cstr_ccat(add_str, '$'); |
if (r & VT_SYM) { |
cstr_cat(add_str, get_tok_str(sv->sym->v, NULL)); |
if (sv->c.i != 0) { |
cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1); |
if ((uint32_t)sv->c.i != 0) { |
cstr_ccat(add_str, '+'); |
} else { |
return; |
1018,23 → 1310,23 |
val = sv->c.i; |
if (modifier == 'n') |
val = -val; |
snprintf(buf, sizeof(buf), "%d", sv->c.i); |
cstr_cat(add_str, buf); |
snprintf(buf, sizeof(buf), "%d", (int)sv->c.i); |
cstr_cat(add_str, buf, -1); |
} else if ((r & VT_VALMASK) == VT_LOCAL) { |
snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i); |
cstr_cat(add_str, buf); |
snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i); |
cstr_cat(add_str, buf, -1); |
} else if (r & VT_LVAL) { |
reg = r & VT_VALMASK; |
if (reg >= VT_CONST) |
error("internal compiler error"); |
tcc_error("internal compiler error"); |
snprintf(buf, sizeof(buf), "(%%%s)", |
get_tok_str(TOK_ASM_eax + reg, NULL)); |
cstr_cat(add_str, buf); |
cstr_cat(add_str, buf, -1); |
} else { |
/* register case */ |
reg = r & VT_VALMASK; |
if (reg >= VT_CONST) |
error("internal compiler error"); |
tcc_error("internal compiler error"); |
/* choose register operand size */ |
if ((sv->type.t & VT_BTYPE) == VT_BYTE) |
1041,6 → 1333,10 |
size = 1; |
else if ((sv->type.t & VT_BTYPE) == VT_SHORT) |
size = 2; |
#ifdef TCC_TARGET_X86_64 |
else if ((sv->type.t & VT_BTYPE) == VT_LLONG) |
size = 8; |
#endif |
else |
size = 4; |
if (size == 1 && reg >= 4) |
1048,14 → 1344,18 |
if (modifier == 'b') { |
if (reg >= 4) |
error("cannot use byte register"); |
tcc_error("cannot use byte register"); |
size = 1; |
} else if (modifier == 'h') { |
if (reg >= 4) |
error("cannot use byte register"); |
tcc_error("cannot use byte register"); |
size = -1; |
} else if (modifier == 'w') { |
size = 2; |
#ifdef TCC_TARGET_X86_64 |
} else if (modifier == 'q') { |
size = 8; |
#endif |
} |
switch(size) { |
1071,14 → 1371,19 |
default: |
reg = TOK_ASM_eax + reg; |
break; |
#ifdef TCC_TARGET_X86_64 |
case 8: |
reg = TOK_ASM_rax + reg; |
break; |
#endif |
} |
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL)); |
cstr_cat(add_str, buf); |
cstr_cat(add_str, buf, -1); |
} |
} |
/* generate prolog and epilog code for asm statment */ |
static void asm_gen_code(ASMOperand *operands, int nb_operands, |
/* generate prolog and epilog code for asm statement */ |
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, |
int nb_outputs, int is_output, |
uint8_t *clobber_regs, |
int out_reg) |
1099,9 → 1404,14 |
/* generate reg save code */ |
for(i = 0; i < NB_SAVED_REGS; i++) { |
reg = reg_saved[i]; |
if (regs_allocated[reg]) |
if (regs_allocated[reg]) { |
#ifdef I386_ASM_16 |
if (tcc_state->seg_size == 16) |
g(0x66); |
#endif |
g(0x50 + reg); |
} |
} |
/* generate load code */ |
for(i = 0; i < nb_operands; i++) { |
1121,8 → 1431,8 |
if (op->is_llong) { |
SValue sv; |
sv = *op->vt; |
sv.c.ul += 4; |
load(TREG_EDX, &sv); |
sv.c.i += 4; |
load(TREG_XDX, &sv); |
} |
} |
} |
1147,8 → 1457,8 |
if (op->is_llong) { |
SValue sv; |
sv = *op->vt; |
sv.c.ul += 4; |
store(TREG_EDX, &sv); |
sv.c.i += 4; |
store(TREG_XDX, &sv); |
} |
} |
} |
1156,13 → 1466,18 |
/* generate reg restore code */ |
for(i = NB_SAVED_REGS - 1; i >= 0; i--) { |
reg = reg_saved[i]; |
if (regs_allocated[reg]) |
if (regs_allocated[reg]) { |
#ifdef I386_ASM_16 |
if (tcc_state->seg_size == 16) |
g(0x66); |
#endif |
g(0x58 + reg); |
} |
} |
} |
} |
static void asm_clobber(uint8_t *clobber_regs, const char *str) |
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str) |
{ |
int reg; |
TokenSym *ts; |
1176,8 → 1491,12 |
reg -= TOK_ASM_eax; |
} else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) { |
reg -= TOK_ASM_ax; |
#ifdef TCC_TARGET_X86_64 |
} else if (reg >= TOK_ASM_rax && reg <= TOK_ASM_rdi) { |
reg -= TOK_ASM_rax; |
#endif |
} else { |
error("invalid clobber register '%s'", str); |
tcc_error("invalid clobber register '%s'", str); |
} |
clobber_regs[reg] = 1; |
} |
/programs/develop/ktcc/trunk/source/i386-asm.h |
---|
1,6 → 1,4 |
DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */ |
DEF_ASM_OP0(popa, 0x61) |
DEF_ASM_OP0(clc, 0xf8) |
DEF_ASM_OP0(clc, 0xf8) /* must be first OP0 */ |
DEF_ASM_OP0(cld, 0xfc) |
DEF_ASM_OP0(cli, 0xfa) |
DEF_ASM_OP0(clts, 0x0f06) |
7,6 → 5,8 |
DEF_ASM_OP0(cmc, 0xf5) |
DEF_ASM_OP0(lahf, 0x9f) |
DEF_ASM_OP0(sahf, 0x9e) |
DEF_ASM_OP0(pusha, 0x60) |
DEF_ASM_OP0(popa, 0x61) |
DEF_ASM_OP0(pushfl, 0x9c) |
DEF_ASM_OP0(popfl, 0x9d) |
DEF_ASM_OP0(pushf, 0x9c) |
33,8 → 33,8 |
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(pause, 0xf390) |
DEF_ASM_OP0(xlat, 0xd7) |
/* strings */ |
74,10 → 74,17 |
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) |
#else |
DEF_ASM_OP0(aword, 0x67) |
DEF_ASM_OP0(addr16, 0x67) |
DEF_ASM_OP0(word, 0x66) |
ALT(DEF_ASM_OP0(word, 0x66)) |
DEF_ASM_OP0(data16, 0x66) |
#endif |
DEF_ASM_OP0(lock, 0xf0) |
DEF_ASM_OP0(rep, 0xf3) |
DEF_ASM_OP0(repe, 0xf3) |
201,6 → 208,9 |
ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR)) |
ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR)) |
ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR)) |
#ifdef I386_ASM_16 |
ALT(DEF_ASM_OP1(jmp, 0xff, 0, OPC_JMP | OPC_WL, OPT_REGW)) |
#endif |
ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32)) |
ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA)) |
209,9 → 219,12 |
ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8)) |
ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA)) |
ALT(DEF_ASM_OP1(setob, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA)) |
DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8) |
DEF_ASM_OP0(leave, 0xc9) |
DEF_ASM_OP0(ret, 0xc3) |
DEF_ASM_OP0(retl,0xc3) |
ALT(DEF_ASM_OP1(retl,0xc2, 0, 0, OPT_IM16)) |
ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16)) |
DEF_ASM_OP0(lret, 0xcb) |
ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16)) |
230,6 → 243,8 |
ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST)) |
ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0)) |
ALT(DEF_ASM_OP2(fadd, 0xdcc0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST)) |
ALT(DEF_ASM_OP2(fmul, 0xdcc8, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST)) |
ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH)) |
ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST)) |
ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0)) |
272,7 → 287,6 |
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) |
350,6 → 364,11 |
DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA) |
DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA) |
#ifdef I386_ASM_16 |
/* 386 */ |
DEF_ASM_OP0(loadall386, 0x0f07) |
#endif |
/* 486 */ |
DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 ) |
ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA )) |
364,7 → 383,15 |
/* pentium pro */ |
ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
#ifdef I386_ASM_16 |
ALT(DEF_ASM_OP2(cmovno, 0x0f41, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
ALT(DEF_ASM_OP2(cmovc, 0x0f42, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
ALT(DEF_ASM_OP2(cmovnc, 0x0f43, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
ALT(DEF_ASM_OP2(cmovz, 0x0f44, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
ALT(DEF_ASM_OP2(cmovnz, 0x0f45, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
ALT(DEF_ASM_OP2(cmovna, 0x0f46, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) |
#endif |
DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 ) |
DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 ) |
DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 ) |
381,6 → 408,7 |
/* mmx */ |
DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */ |
DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX ) |
ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 )) |
DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) |
438,6 → 466,32 |
DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) |
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) |
/* sse */ |
DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) |
ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) |
DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) |
ALT(DEF_ASM_OP2(movaps, 0x0f29, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) |
DEF_ASM_OP2(movhps, 0x0f16, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) |
ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) |
DEF_ASM_OP2(addps, 0x0f58, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(cvtpi2ps, 0x0f2a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_SSE ) |
DEF_ASM_OP2(cvtps2pi, 0x0f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX ) |
DEF_ASM_OP2(cvttps2pi, 0x0f2c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX ) |
DEF_ASM_OP2(divps, 0x0f5e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(maxps, 0x0f5f, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(minps, 0x0f5d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(mulps, 0x0f59, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(pavgb, 0x0fe0, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(pavgw, 0x0fe3, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(pmaxsw, 0x0fee, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) |
DEF_ASM_OP2(pmaxub, 0x0fde, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) |
DEF_ASM_OP2(pminsw, 0x0fea, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) |
DEF_ASM_OP2(pminub, 0x0fda, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) |
DEF_ASM_OP2(rcpss, 0x0f53, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(rsqrtps, 0x0f52, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) |
#undef ALT |
#undef DEF_ASM_OP0 |
#undef DEF_ASM_OP0L |
/programs/develop/ktcc/trunk/source/i386-gen.c |
---|
18,8 → 18,11 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
#ifdef TARGET_DEFS_ONLY |
/* number of available registers */ |
#define NB_REGS 4 |
#define NB_ASM_REGS 8 |
/* a register can belong to several classes. The classes must be |
sorted from more general to more precise (see gv2() code which does |
40,15 → 43,9 |
TREG_ECX, |
TREG_EDX, |
TREG_ST0, |
TREG_ESP = 4 |
}; |
int reg_classes[NB_REGS] = { |
/* eax */ RC_INT | RC_EAX, |
/* ecx */ RC_INT | RC_ECX, |
/* edx */ RC_INT | RC_EDX, |
/* st0 */ RC_FLOAT | RC_ST0, |
}; |
/* return registers for function */ |
#define REG_IRET TREG_EAX /* single word int return register */ |
#define REG_LRET TREG_EDX /* second word return register (for long long) */ |
59,7 → 56,7 |
/* defined if structures are passed as pointers. Otherwise structures |
are directly pushed on stack. */ |
//#define FUNC_STRUCT_PARAM_AS_PTR |
/* #define FUNC_STRUCT_PARAM_AS_PTR */ |
/* pointer size, in bytes */ |
#define PTR_SIZE 4 |
70,6 → 67,9 |
/* maximum alignment (for aligned attribute support) */ |
#define MAX_ALIGN 8 |
#define psym oad |
/******************************************************/ |
/* ELF defines */ |
77,6 → 77,7 |
/* relocation type for 32 bit data relocation */ |
#define R_DATA_32 R_386_32 |
#define R_DATA_PTR R_386_32 |
#define R_JMP_SLOT R_386_JMP_SLOT |
#define R_COPY R_386_COPY |
84,13 → 85,25 |
#define ELF_PAGE_SIZE 0x1000 |
/******************************************************/ |
#else /* ! TARGET_DEFS_ONLY */ |
/******************************************************/ |
#include "tcc.h" |
ST_DATA const int reg_classes[NB_REGS] = { |
/* eax */ RC_INT | RC_EAX, |
/* ecx */ RC_INT | RC_ECX, |
/* edx */ RC_INT | RC_EDX, |
/* st0 */ RC_FLOAT | RC_ST0, |
}; |
static unsigned long func_sub_sp_offset; |
static unsigned long func_bound_offset; |
static int func_ret_sub; |
#ifdef CONFIG_TCC_BCHECK |
static addr_t func_bound_offset; |
#endif |
/* XXX: make it faster ? */ |
void g(int c) |
ST_FUNC void g(int c) |
{ |
int ind1; |
ind1 = ind + 1; |
100,7 → 113,7 |
ind = ind1; |
} |
void o(unsigned int c) |
ST_FUNC void o(unsigned int c) |
{ |
while (c) { |
g(c); |
108,8 → 121,14 |
} |
} |
void gen_le32(int c) |
ST_FUNC void gen_le16(int v) |
{ |
g(v); |
g(v >> 8); |
} |
ST_FUNC void gen_le32(int c) |
{ |
g(c); |
g(c >> 8); |
g(c >> 16); |
117,18 → 136,17 |
} |
/* output a symbol and patch all calls to it */ |
void gsym_addr(int t, int a) |
ST_FUNC void gsym_addr(int t, int a) |
{ |
int n, *ptr; |
while (t) { |
ptr = (int *)(cur_text_section->data + t); |
n = *ptr; /* next value */ |
*ptr = a - t - 4; |
unsigned char *ptr = cur_text_section->data + t; |
uint32_t n = read32le(ptr); /* next value */ |
write32le(ptr, a - t - 4); |
t = n; |
} |
} |
void gsym(int t) |
ST_FUNC void gsym(int t) |
{ |
gsym_addr(t, ind); |
} |
138,7 → 156,7 |
#define psym oad |
/* instruction + 4 bytes data. Return the address of the data */ |
static int oad(int c, int s) |
ST_FUNC int oad(int c, int s) |
{ |
int ind1; |
146,7 → 164,7 |
ind1 = ind + 4; |
if (ind1 > cur_text_section->data_allocated) |
section_realloc(cur_text_section, ind1); |
*(int *)(cur_text_section->data + ind) = s; |
write32le(cur_text_section->data + ind, s); |
s = ind; |
ind = ind1; |
return s; |
153,7 → 171,7 |
} |
/* output constant with relocation if 'r & VT_SYM' is true */ |
static void gen_addr32(int r, Sym *sym, int c) |
ST_FUNC void gen_addr32(int r, Sym *sym, int c) |
{ |
if (r & VT_SYM) |
greloc(cur_text_section, sym, ind, R_386_32); |
160,6 → 178,13 |
gen_le32(c); |
} |
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) |
{ |
if (r & VT_SYM) |
greloc(cur_text_section, sym, ind, R_386_PC32); |
gen_le32(c - 4); |
} |
/* generate a modrm reference. 'op_reg' contains the addtionnal 3 |
opcode bits */ |
static void gen_modrm(int op_reg, int r, Sym *sym, int c) |
183,25 → 208,33 |
} |
} |
/* load 'r' from value 'sv' */ |
void load(int r, SValue *sv) |
ST_FUNC void load(int r, SValue *sv) |
{ |
int v, t, ft, fc, fr; |
SValue v1; |
#ifdef TCC_TARGET_PE |
SValue v2; |
sv = pe_getimport(sv, &v2); |
#endif |
fr = sv->r; |
ft = sv->type.t; |
fc = sv->c.ul; |
fc = sv->c.i; |
ft &= ~(VT_VOLATILE | VT_CONSTANT); |
v = fr & VT_VALMASK; |
if (fr & VT_LVAL) { |
if (v == VT_LLOCAL) { |
v1.type.t = VT_INT; |
v1.r = VT_LOCAL | VT_LVAL; |
v1.c.ul = fc; |
load(r, &v1); |
v1.c.i = fc; |
fr = r; |
if (!(reg_classes[fr] & RC_INT)) |
fr = get_reg(RC_INT); |
load(fr, &v1); |
} |
if ((ft & VT_BTYPE) == VT_FLOAT) { |
o(0xd9); /* flds */ |
212,7 → 245,7 |
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) { |
o(0xdb); /* fldt */ |
r = 5; |
} else if ((ft & VT_TYPE) == VT_BYTE) { |
} else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { |
o(0xbe0f); /* movsbl */ |
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { |
o(0xb60f); /* movzbl */ |
229,8 → 262,13 |
o(0xb8 + r); /* mov $xx, r */ |
gen_addr32(fr, sv->sym, fc); |
} else if (v == VT_LOCAL) { |
if (fc) { |
o(0x8d); /* lea xxx(%ebp), r */ |
gen_modrm(r, VT_LOCAL, sv->sym, fc); |
} else { |
o(0x89); |
o(0xe8 + r); /* mov %ebp, r */ |
} |
} else if (v == VT_CMP) { |
oad(0xb8 + r, 0); /* mov $0, r */ |
o(0x0f); /* setxx %br */ |
250,13 → 288,19 |
} |
/* store register 'r' in lvalue 'v' */ |
void store(int r, SValue *v) |
ST_FUNC void store(int r, SValue *v) |
{ |
int fr, bt, ft, fc; |
#ifdef TCC_TARGET_PE |
SValue v2; |
v = pe_getimport(v, &v2); |
#endif |
ft = v->type.t; |
fc = v->c.ul; |
fc = v->c.i; |
fr = v->r & VT_VALMASK; |
ft &= ~(VT_VOLATILE | VT_CONSTANT); |
bt = ft & VT_BTYPE; |
/* XXX: incorrect if float reg to reg */ |
if (bt == VT_FLOAT) { |
296,6 → 340,15 |
} |
} |
static void gen_static_call(int v) |
{ |
Sym *sym; |
sym = external_global_sym(v, &func_old_type, 0); |
oad(0xe8, -4); |
greloc(cur_text_section, sym, ind-4, R_386_PC32); |
} |
/* 'is_jmp' is '1' if it is a jump */ |
static void gcall_or_jmp(int is_jmp) |
{ |
311,7 → 364,7 |
put_elf_reloc(symtab_section, cur_text_section, |
ind + 1, R_386_PC32, 0); |
} |
oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */ |
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ |
} else { |
/* otherwise, indirect call */ |
r = gv(RC_INT); |
321,11 → 374,39 |
} |
static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; |
static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; |
/* Return the number of registers needed to return the struct, or 0 if |
returning via struct pointer. */ |
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) |
{ |
#ifdef TCC_TARGET_PE |
int size, align; |
*ret_align = 1; // Never have to re-align return values for x86 |
*regsize = 4; |
size = type_size(vt, &align); |
if (size > 8) { |
return 0; |
} else if (size > 4) { |
ret->ref = NULL; |
ret->t = VT_LLONG; |
return 1; |
} else { |
ret->ref = NULL; |
ret->t = VT_INT; |
return 1; |
} |
#else |
*ret_align = 1; // Never have to re-align return values for x86 |
return 0; |
#endif |
} |
/* Generate function call. The function address is pushed first, then |
all the parameters in call order. This functions pops all the |
parameters and the function address. */ |
void gfunc_call(int nb_args) |
ST_FUNC void gfunc_call(int nb_args) |
{ |
int size, align, r, args_size, i, func_call; |
Sym *func_sym; |
379,21 → 460,34 |
} |
save_regs(0); /* save used temporary registers */ |
func_sym = vtop->type.ref; |
func_call = func_sym->r; |
func_call = func_sym->a.func_call; |
/* fast call case */ |
if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) { |
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || |
func_call == FUNC_FASTCALLW) { |
int fastcall_nb_regs; |
uint8_t *fastcall_regs_ptr; |
if (func_call == FUNC_FASTCALLW) { |
fastcall_regs_ptr = fastcallw_regs; |
fastcall_nb_regs = 2; |
} else { |
fastcall_regs_ptr = fastcall_regs; |
fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1; |
} |
for(i = 0;i < fastcall_nb_regs; i++) { |
if (args_size <= 0) |
break; |
o(0x58 + fastcall_regs[i]); /* pop r */ |
o(0x58 + fastcall_regs_ptr[i]); /* pop r */ |
/* XXX: incorrect for struct/floats */ |
args_size -= 4; |
} |
} |
#ifndef TCC_TARGET_PE |
else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) |
args_size -= 4; |
#endif |
gcall_or_jmp(0); |
if (args_size && func_sym->r != FUNC_STDCALL) |
if (args_size && func_call != FUNC_STDCALL) |
gadd_sp(args_size); |
vtop--; |
} |
405,21 → 499,29 |
#endif |
/* generate function prolog of type 't' */ |
void gfunc_prolog(CType *func_type) |
ST_FUNC void gfunc_prolog(CType *func_type) |
{ |
int addr, align, size, func_call, fastcall_nb_regs; |
int param_index, param_addr; |
uint8_t *fastcall_regs_ptr; |
Sym *sym; |
CType *type; |
sym = func_type->ref; |
func_call = sym->r; |
func_call = sym->a.func_call; |
addr = 8; |
loc = 0; |
func_vc = 0; |
if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) { |
fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1; |
fastcall_regs_ptr = fastcall_regs; |
} else if (func_call == FUNC_FASTCALLW) { |
fastcall_nb_regs = 2; |
fastcall_regs_ptr = fastcallw_regs; |
} else { |
fastcall_nb_regs = 0; |
fastcall_regs_ptr = NULL; |
} |
param_index = 0; |
428,7 → 530,13 |
/* if the function returns a structure, then add an |
implicit pointer parameter */ |
func_vt = sym->type; |
func_var = (sym->c == FUNC_ELLIPSIS); |
#ifdef TCC_TARGET_PE |
size = type_size(&func_vt,&align); |
if (((func_vt.t & VT_BTYPE) == VT_STRUCT) && (size > 8)) { |
#else |
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { |
#endif |
/* XXX: fastcall case ? */ |
func_vc = addr; |
addr += 4; |
449,7 → 557,7 |
/* save FASTCALL register */ |
loc -= 4; |
o(0x89); /* movl */ |
gen_modrm(fastcall_regs[param_index], VT_LOCAL, NULL, loc); |
gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); |
param_addr = loc; |
} else { |
param_addr = addr; |
456,7 → 564,7 |
addr += size; |
} |
sym_push(sym->v & ~SYM_FIELD, type, |
VT_LOCAL | VT_LVAL, param_addr); |
VT_LOCAL | lvalue_type(type->t), param_addr); |
param_index++; |
} |
func_ret_sub = 0; |
463,27 → 571,34 |
/* pascal type call ? */ |
if (func_call == FUNC_STDCALL) |
func_ret_sub = addr - 8; |
#ifndef TCC_TARGET_PE |
else if (func_vc) |
func_ret_sub = 4; |
#endif |
#ifdef CONFIG_TCC_BCHECK |
/* leave some room for bound checking code */ |
if (do_bounds_check) { |
if (tcc_state->do_bounds_check) { |
oad(0xb8, 0); /* lbound section pointer */ |
oad(0xb8, 0); /* call to function */ |
func_bound_offset = lbounds_section->data_offset; |
} |
#endif |
} |
/* generate function epilog */ |
void gfunc_epilog(void) |
ST_FUNC void gfunc_epilog(void) |
{ |
int v, saved_ind; |
addr_t v, saved_ind; |
#ifdef CONFIG_TCC_BCHECK |
if (do_bounds_check && func_bound_offset != lbounds_section->data_offset) { |
int saved_ind; |
int *bounds_ptr; |
Sym *sym, *sym_data; |
if (tcc_state->do_bounds_check |
&& func_bound_offset != lbounds_section->data_offset) { |
addr_t saved_ind; |
addr_t *bounds_ptr; |
Sym *sym_data; |
/* add end of table info */ |
bounds_ptr = section_ptr_add(lbounds_section, sizeof(int)); |
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); |
*bounds_ptr = 0; |
/* generate bound local allocation */ |
saved_ind = ind; |
493,10 → 608,8 |
greloc(cur_text_section, sym_data, |
ind + 1, R_386_32); |
oad(0xb8, 0); /* mov %eax, xxx */ |
sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0); |
greloc(cur_text_section, sym, |
ind + 1, R_386_PC32); |
oad(0xe8, -4); |
gen_static_call(TOK___bound_local_new); |
ind = saved_ind; |
/* generate bound check local freeing */ |
o(0x5250); /* save returned value, if any */ |
503,10 → 616,8 |
greloc(cur_text_section, sym_data, |
ind + 1, R_386_32); |
oad(0xb8, 0); /* mov %eax, xxx */ |
sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0); |
greloc(cur_text_section, sym, |
ind + 1, R_386_PC32); |
oad(0xe8, -4); |
gen_static_call(TOK___bound_local_delete); |
o(0x585a); /* restore returned value, if any */ |
} |
#endif |
525,10 → 636,8 |
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; |
#ifdef TCC_TARGET_PE |
if (v >= 4096) { |
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); |
oad(0xb8, v); /* mov stacksize, %eax */ |
oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ |
greloc(cur_text_section, sym, ind-4, R_386_PC32); |
gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */ |
} else |
#endif |
{ |
543,13 → 652,13 |
} |
/* generate a jump to a label */ |
int gjmp(int t) |
ST_FUNC int gjmp(int t) |
{ |
return psym(0xe9, t); |
} |
/* generate a jump to a fixed address */ |
void gjmp_addr(int a) |
ST_FUNC void gjmp_addr(int a) |
{ |
int r; |
r = a - ind - 2; |
562,11 → 671,9 |
} |
/* generate a test. set 'inv' to invert test. Stack entry is popped */ |
int gtst(int inv, int t) |
ST_FUNC int gtst(int inv, int t) |
{ |
int v, *p; |
v = vtop->r & VT_VALMASK; |
int v = vtop->r & VT_VALMASK; |
if (v == VT_CMP) { |
/* fast case : can jump directly since flags are set */ |
g(0x0f); |
575,38 → 682,24 |
/* && or || optimization */ |
if ((v & 1) == inv) { |
/* insert vtop->c jump list in t */ |
p = &vtop->c.i; |
while (*p != 0) |
p = (int *)(cur_text_section->data + *p); |
*p = t; |
uint32_t n1, n = vtop->c.i; |
if (n) { |
while ((n1 = read32le(cur_text_section->data + n))) |
n = n1; |
write32le(cur_text_section->data + n, t); |
t = vtop->c.i; |
} |
} else { |
t = gjmp(t); |
gsym(vtop->c.i); |
} |
} else { |
if (is_float(vtop->type.t)) { |
vpushi(0); |
gen_op(TOK_NE); |
} |
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
/* constant jmp optimization */ |
if ((vtop->c.i != 0) != inv) |
t = gjmp(t); |
} else { |
v = gv(RC_INT); |
o(0x85); |
o(0xc0 + v * 9); |
g(0x0f); |
t = psym(0x85 ^ inv, t); |
} |
} |
vtop--; |
return t; |
} |
/* generate an integer binary operation */ |
void gen_opi(int op) |
ST_FUNC void gen_opi(int op) |
{ |
int r, fr, opc, c; |
622,10 → 715,16 |
vswap(); |
c = vtop->c.i; |
if (c == (char)c) { |
/* XXX: generate inc and dec for smaller code ? */ |
/* generate inc and dec for smaller code */ |
if (c==1 && opc==0) { |
o (0x40 | r); // inc |
} else if (c==1 && opc==5) { |
o (0x48 | r); // dec |
} else { |
o(0x83); |
o(0xc0 | (opc << 3) | r); |
g(c); |
} |
} else { |
o(0x81); |
oad(0xc0 | (opc << 3) | r, c); |
740,7 → 839,7 |
/* generate a floating point operation 'v = t1 op t2' instruction. The |
two operands are guaranted to have the same floating point type */ |
/* XXX: need to use ST1 too */ |
void gen_opf(int op) |
ST_FUNC void gen_opf(int op) |
{ |
int a, ft, fc, swapped, r; |
777,7 → 876,10 |
swapped = 0; |
if (swapped) |
o(0xc9d9); /* fxch %st(1) */ |
if (op == TOK_EQ || op == TOK_NE) |
o(0xe9da); /* fucompp */ |
else |
o(0xd9de); /* fcompp */ |
o(0xe0df); /* fnstsw %ax */ |
if (op == TOK_EQ) { |
o(0x45e480); /* and $0x45, %ah */ |
823,7 → 925,7 |
break; |
} |
ft = vtop->type.t; |
fc = vtop->c.ul; |
fc = vtop->c.i; |
if ((ft & VT_BTYPE) == VT_LDOUBLE) { |
o(0xde); /* fxxxp %st, %st(1) */ |
o(0xc1 + (a << 3)); |
835,7 → 937,7 |
r = get_reg(RC_INT); |
v1.type.t = VT_INT; |
v1.r = VT_LOCAL | VT_LVAL; |
v1.c.ul = fc; |
v1.c.i = fc; |
load(r, &v1); |
fc = 0; |
} |
852,7 → 954,7 |
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int' |
and 'long long' cases. */ |
void gen_cvt_itof(int t) |
ST_FUNC void gen_cvt_itof(int t) |
{ |
save_reg(TREG_ST0); |
gv(RC_INT); |
881,58 → 983,47 |
} |
/* convert fp to int 't' type */ |
/* XXX: handle long long case */ |
void gen_cvt_ftoi(int t) |
ST_FUNC void gen_cvt_ftoi(int t) |
{ |
int r, r2, size; |
Sym *sym; |
CType ushort_type; |
ushort_type.t = VT_SHORT | VT_UNSIGNED; |
#ifndef COMMIT_4ad186c5ef61_IS_FIXED |
/* a good version but it takes a more time to execute */ |
gv(RC_FLOAT); |
if (t != VT_INT) |
size = 8; |
save_reg(TREG_EAX); |
save_reg(TREG_EDX); |
gen_static_call(TOK___tcc_cvt_ftol); |
vtop->r = TREG_EAX; /* mark reg as used */ |
if (t == VT_LLONG) |
vtop->r2 = TREG_EDX; |
#else |
/* a new version with a bug: t2a = 44100312 */ |
/* |
#include<stdio.h> |
int main() { |
int t1 = 176401255; |
float f = 0.25f; |
int t2a = (int)(t1 * f); // must be 44100313 |
int t2b = (int)(t1 * (float)0.25f); |
printf("t2a=%d t2b=%d \n",t2a,t2b); |
return 0; |
} |
*/ |
int bt = vtop->type.t & VT_BTYPE; |
if (bt == VT_FLOAT) |
vpush_global_sym(&func_old_type, TOK___fixsfdi); |
else if (bt == VT_LDOUBLE) |
vpush_global_sym(&func_old_type, TOK___fixxfdi); |
else |
size = 4; |
o(0x2dd9); /* ldcw xxx */ |
sym = external_global_sym(TOK___tcc_int_fpu_control, |
&ushort_type, VT_LVAL); |
greloc(cur_text_section, sym, |
ind, R_386_32); |
gen_le32(0); |
oad(0xec81, size); /* sub $xxx, %esp */ |
if (size == 4) |
o(0x1cdb); /* fistpl */ |
else |
o(0x3cdf); /* fistpll */ |
o(0x24); |
o(0x2dd9); /* ldcw xxx */ |
sym = external_global_sym(TOK___tcc_fpu_control, |
&ushort_type, VT_LVAL); |
greloc(cur_text_section, sym, |
ind, R_386_32); |
gen_le32(0); |
r = get_reg(RC_INT); |
o(0x58 + r); /* pop r */ |
if (size == 8) { |
if (t == VT_LLONG) { |
vtop->r = r; /* mark reg as used */ |
r2 = get_reg(RC_INT); |
o(0x58 + r2); /* pop r2 */ |
vtop->r2 = r2; |
} else { |
o(0x04c483); /* add $4, %esp */ |
vpush_global_sym(&func_old_type, TOK___fixdfdi); |
vswap(); |
gfunc_call(1); |
vpushi(0); |
vtop->r = REG_IRET; |
vtop->r2 = REG_LRET; |
#endif |
} |
} |
vtop->r = r; |
} |
/* convert from one floating point type to another */ |
void gen_cvt_ftof(int t) |
ST_FUNC void gen_cvt_ftof(int t) |
{ |
/* all we have to do on i386 is to put the float in a register */ |
gv(RC_FLOAT); |
939,7 → 1030,7 |
} |
/* computed goto support */ |
void ggoto(void) |
ST_FUNC void ggoto(void) |
{ |
gcall_or_jmp(1); |
vtop--; |
949,10 → 1040,8 |
#ifdef CONFIG_TCC_BCHECK |
/* generate a bounded pointer addition */ |
void gen_bounded_ptr_add(void) |
ST_FUNC void gen_bounded_ptr_add(void) |
{ |
Sym *sym; |
/* prepare fast i386 function call (args in eax and edx) */ |
gv2(RC_EAX, RC_EDX); |
/* save all temporary registers */ |
959,22 → 1048,19 |
vtop -= 2; |
save_regs(0); |
/* do a fast function call */ |
sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0); |
greloc(cur_text_section, sym, |
ind + 1, R_386_PC32); |
oad(0xe8, -4); |
gen_static_call(TOK___bound_ptr_add); |
/* returned pointer is in eax */ |
vtop++; |
vtop->r = TREG_EAX | VT_BOUNDED; |
/* address of bounding function call point */ |
vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); |
vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); |
} |
/* patch pointer addition in vtop so that pointer dereferencing is |
also tested */ |
void gen_bounded_ptr_deref(void) |
ST_FUNC void gen_bounded_ptr_deref(void) |
{ |
int func; |
addr_t func; |
int size, align; |
Elf32_Rel *rel; |
Sym *sym; |
997,7 → 1083,7 |
case 12: func = TOK___bound_ptr_indir12; break; |
case 16: func = TOK___bound_ptr_indir16; break; |
default: |
error("unhandled size when derefencing bounded pointer"); |
tcc_error("unhandled size when dereferencing bounded pointer"); |
func = 0; |
break; |
} |
1004,7 → 1090,7 |
/* patch relocation */ |
/* XXX: find a better solution ? */ |
rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul); |
rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i); |
sym = external_global_sym(func, &func_old_type, 0); |
if (!sym->c) |
put_extern_sym(sym, NULL, 0, 0); |
1012,6 → 1098,40 |
} |
#endif |
/* Save the stack pointer onto the stack */ |
ST_FUNC void gen_vla_sp_save(int addr) { |
/* mov %esp,addr(%ebp)*/ |
o(0x89); |
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); |
} |
/* Restore the SP from a location on the stack */ |
ST_FUNC void gen_vla_sp_restore(int addr) { |
o(0x8b); |
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); |
} |
/* Subtract from the stack pointer, and push the resulting value onto the stack */ |
ST_FUNC void gen_vla_alloc(CType *type, int align) { |
#ifdef TCC_TARGET_PE |
/* alloca does more than just adjust %rsp on Windows */ |
vpush_global_sym(&func_old_type, TOK_alloca); |
vswap(); /* Move alloca ref past allocation size */ |
gfunc_call(1); |
#else |
int r; |
r = gv(RC_INT); /* allocation size */ |
/* sub r,%rsp */ |
o(0x2b); |
o(0xe0 | r); |
/* We align to 16 bytes rather than align */ |
/* and ~15, %esp */ |
o(0xf0e483); |
vpop(); |
#endif |
} |
/* end of X86 code generator */ |
/*************************************************************/ |
#endif |
/*************************************************************/ |
/programs/develop/ktcc/trunk/source/i386-tok.h |
---|
0,0 → 1,244 |
/* ------------------------------------------------------------------ */ |
/* WARNING: relative order of tokens is important. */ |
/* register */ |
DEF_ASM(al) |
DEF_ASM(cl) |
DEF_ASM(dl) |
DEF_ASM(bl) |
DEF_ASM(ah) |
DEF_ASM(ch) |
DEF_ASM(dh) |
DEF_ASM(bh) |
DEF_ASM(ax) |
DEF_ASM(cx) |
DEF_ASM(dx) |
DEF_ASM(bx) |
DEF_ASM(sp) |
DEF_ASM(bp) |
DEF_ASM(si) |
DEF_ASM(di) |
DEF_ASM(eax) |
DEF_ASM(ecx) |
DEF_ASM(edx) |
DEF_ASM(ebx) |
DEF_ASM(esp) |
DEF_ASM(ebp) |
DEF_ASM(esi) |
DEF_ASM(edi) |
#ifdef TCC_TARGET_X86_64 |
DEF_ASM(rax) |
DEF_ASM(rcx) |
DEF_ASM(rdx) |
DEF_ASM(rbx) |
DEF_ASM(rsp) |
DEF_ASM(rbp) |
DEF_ASM(rsi) |
DEF_ASM(rdi) |
#endif |
DEF_ASM(mm0) |
DEF_ASM(mm1) |
DEF_ASM(mm2) |
DEF_ASM(mm3) |
DEF_ASM(mm4) |
DEF_ASM(mm5) |
DEF_ASM(mm6) |
DEF_ASM(mm7) |
DEF_ASM(xmm0) |
DEF_ASM(xmm1) |
DEF_ASM(xmm2) |
DEF_ASM(xmm3) |
DEF_ASM(xmm4) |
DEF_ASM(xmm5) |
DEF_ASM(xmm6) |
DEF_ASM(xmm7) |
DEF_ASM(cr0) |
DEF_ASM(cr1) |
DEF_ASM(cr2) |
DEF_ASM(cr3) |
DEF_ASM(cr4) |
DEF_ASM(cr5) |
DEF_ASM(cr6) |
DEF_ASM(cr7) |
DEF_ASM(tr0) |
DEF_ASM(tr1) |
DEF_ASM(tr2) |
DEF_ASM(tr3) |
DEF_ASM(tr4) |
DEF_ASM(tr5) |
DEF_ASM(tr6) |
DEF_ASM(tr7) |
DEF_ASM(db0) |
DEF_ASM(db1) |
DEF_ASM(db2) |
DEF_ASM(db3) |
DEF_ASM(db4) |
DEF_ASM(db5) |
DEF_ASM(db6) |
DEF_ASM(db7) |
DEF_ASM(dr0) |
DEF_ASM(dr1) |
DEF_ASM(dr2) |
DEF_ASM(dr3) |
DEF_ASM(dr4) |
DEF_ASM(dr5) |
DEF_ASM(dr6) |
DEF_ASM(dr7) |
DEF_ASM(es) |
DEF_ASM(cs) |
DEF_ASM(ss) |
DEF_ASM(ds) |
DEF_ASM(fs) |
DEF_ASM(gs) |
DEF_ASM(st) |
/* generic two operands */ |
DEF_BWLX(mov) |
DEF_BWLX(add) |
DEF_BWLX(or) |
DEF_BWLX(adc) |
DEF_BWLX(sbb) |
DEF_BWLX(and) |
DEF_BWLX(sub) |
DEF_BWLX(xor) |
DEF_BWLX(cmp) |
/* unary ops */ |
DEF_BWLX(inc) |
DEF_BWLX(dec) |
DEF_BWLX(not) |
DEF_BWLX(neg) |
DEF_BWLX(mul) |
DEF_BWLX(imul) |
DEF_BWLX(div) |
DEF_BWLX(idiv) |
DEF_BWLX(xchg) |
DEF_BWLX(test) |
/* shifts */ |
DEF_BWLX(rol) |
DEF_BWLX(ror) |
DEF_BWLX(rcl) |
DEF_BWLX(rcr) |
DEF_BWLX(shl) |
DEF_BWLX(shr) |
DEF_BWLX(sar) |
DEF_ASM(shldw) |
DEF_ASM(shldl) |
DEF_ASM(shld) |
DEF_ASM(shrdw) |
DEF_ASM(shrdl) |
DEF_ASM(shrd) |
DEF_ASM(pushw) |
DEF_ASM(pushl) |
#ifdef TCC_TARGET_X86_64 |
DEF_ASM(pushq) |
#endif |
DEF_ASM(push) |
DEF_ASM(popw) |
DEF_ASM(popl) |
#ifdef TCC_TARGET_X86_64 |
DEF_ASM(popq) |
#endif |
DEF_ASM(pop) |
DEF_BWL(in) |
DEF_BWL(out) |
DEF_WL(movzb) |
DEF_ASM(movzwl) |
DEF_ASM(movsbw) |
DEF_ASM(movsbl) |
DEF_ASM(movswl) |
#ifdef TCC_TARGET_X86_64 |
DEF_ASM(movslq) |
#endif |
DEF_WLX(lea) |
DEF_ASM(les) |
DEF_ASM(lds) |
DEF_ASM(lss) |
DEF_ASM(lfs) |
DEF_ASM(lgs) |
DEF_ASM(call) |
DEF_ASM(jmp) |
DEF_ASM(lcall) |
DEF_ASM(ljmp) |
DEF_ASMTEST(j,) |
DEF_ASMTEST(set,) |
DEF_ASMTEST(set,b) |
DEF_ASMTEST(cmov,) |
DEF_WLX(bsf) |
DEF_WLX(bsr) |
DEF_WLX(bt) |
DEF_WLX(bts) |
DEF_WLX(btr) |
DEF_WLX(btc) |
DEF_WLX(lsl) |
/* generic FP ops */ |
DEF_FP(add) |
DEF_FP(mul) |
DEF_ASM(fcom) |
DEF_ASM(fcom_1) /* non existent op, just to have a regular table */ |
DEF_FP1(com) |
DEF_FP(comp) |
DEF_FP(sub) |
DEF_FP(subr) |
DEF_FP(div) |
DEF_FP(divr) |
DEF_BWLX(xadd) |
DEF_BWLX(cmpxchg) |
/* string ops */ |
DEF_BWLX(cmps) |
DEF_BWLX(scmp) |
DEF_BWL(ins) |
DEF_BWL(outs) |
DEF_BWLX(lods) |
DEF_BWLX(slod) |
DEF_BWLX(movs) |
DEF_BWLX(smov) |
DEF_BWLX(scas) |
DEF_BWLX(ssca) |
DEF_BWLX(stos) |
DEF_BWLX(ssto) |
/* generic asm ops */ |
#define ALT(x) |
#define DEF_ASM_OP0(name, opcode) DEF_ASM(name) |
#define DEF_ASM_OP0L(name, opcode, group, instr_type) |
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) |
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) |
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) |
#ifdef TCC_TARGET_X86_64 |
# include "x86_64-asm.h" |
#else |
# include "i386-asm.h" |
#endif |
#define ALT(x) |
#define DEF_ASM_OP0(name, opcode) |
#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name) |
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name) |
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name) |
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name) |
#ifdef TCC_TARGET_X86_64 |
# include "x86_64-asm.h" |
#else |
# include "i386-asm.h" |
#endif |
/programs/develop/ktcc/trunk/source/il-gen.c |
---|
3,19 → 3,19 |
* |
* Copyright (c) 2002 Fabrice Bellard |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2 of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
/* number of available registers */ |
41,7 → 41,7 |
REG_ST2, |
}; |
int reg_classes[NB_REGS] = { |
const int reg_classes[NB_REGS] = { |
/* ST0 */ RC_ST | RC_ST0, |
/* ST1 */ RC_ST | RC_ST1, |
/* ST2 */ RC_ST, |
53,11 → 53,11 |
#define REG_FRET REG_ST0 /* float return register */ |
/* defined if function parameters must be evaluated in reverse order */ |
//#define INVERT_FUNC_PARAMS |
/* #define INVERT_FUNC_PARAMS */ |
/* defined if structures are passed as pointers. Otherwise structures |
are directly pushed on stack. */ |
//#define FUNC_STRUCT_PARAM_AS_PTR |
/* #define FUNC_STRUCT_PARAM_AS_PTR */ |
/* pointer size, in bytes */ |
#define PTR_SIZE 4 |
193,7 → 193,7 |
pstrcat(buf, buf_size, tstr); |
break; |
case VT_STRUCT: |
error("structures not handled yet"); |
tcc_error("structures not handled yet"); |
break; |
case VT_FUNC: |
s = sym_find((unsigned)t >> VT_STRUCT_SHIFT); |
387,7 → 387,7 |
void gfunc_param(GFuncContext *c) |
{ |
if ((vtop->t & VT_BTYPE) == VT_STRUCT) { |
error("structures passed as value not handled yet"); |
tcc_error("structures passed as value not handled yet"); |
} else { |
/* simply push on stack */ |
gv(RC_ST0); |
441,6 → 441,7 |
/* if the function returns a structure, then add an |
implicit pointer parameter */ |
func_vt = sym->t; |
func_var = (sym->c == FUNC_ELLIPSIS); |
if ((func_vt & VT_BTYPE) == VT_STRUCT) { |
func_vc = addr; |
addr++; |
449,7 → 450,7 |
while ((sym = sym->next) != NULL) { |
u = sym->t; |
sym_push(sym->v & ~SYM_FIELD, u, |
VT_LOCAL | VT_LVAL, addr); |
VT_LOCAL | lvalue_type(sym->type.t), addr); |
addr++; |
} |
} |
528,20 → 529,7 |
t = gjmp(t); |
gsym(vtop->c.i); |
} |
} else { |
if (is_float(vtop->t)) { |
vpushi(0); |
gen_op(TOK_NE); |
} |
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) { |
/* constant jmp optimization */ |
if ((vtop->c.i != 0) != inv) |
t = gjmp(t); |
} else { |
v = gv(RC_INT); |
t = out_opj(IL_OP_BRTRUE - inv, t); |
} |
} |
vtop--; |
return t; |
} |
/programs/develop/ktcc/trunk/source/include/float.h |
---|
0,0 → 1,57 |
#ifndef _FLOAT_H_ |
#define _FLOAT_H_ |
#define FLT_RADIX 2 |
/* IEEE float */ |
#define FLT_MANT_DIG 24 |
#define FLT_DIG 6 |
#define FLT_ROUNDS 1 |
#define FLT_EPSILON 1.19209290e-07F |
#define FLT_MIN_EXP (-125) |
#define FLT_MIN 1.17549435e-38F |
#define FLT_MIN_10_EXP (-37) |
#define FLT_MAX_EXP 128 |
#define FLT_MAX 3.40282347e+38F |
#define FLT_MAX_10_EXP 38 |
/* IEEE double */ |
#define DBL_MANT_DIG 53 |
#define DBL_DIG 15 |
#define DBL_EPSILON 2.2204460492503131e-16 |
#define DBL_MIN_EXP (-1021) |
#define DBL_MIN 2.2250738585072014e-308 |
#define DBL_MIN_10_EXP (-307) |
#define DBL_MAX_EXP 1024 |
#define DBL_MAX 1.7976931348623157e+308 |
#define DBL_MAX_10_EXP 308 |
/* horrible intel long double */ |
#if defined __i386__ || defined __x86_64__ |
#define LDBL_MANT_DIG 64 |
#define LDBL_DIG 18 |
#define LDBL_EPSILON 1.08420217248550443401e-19L |
#define LDBL_MIN_EXP (-16381) |
#define LDBL_MIN 3.36210314311209350626e-4932L |
#define LDBL_MIN_10_EXP (-4931) |
#define LDBL_MAX_EXP 16384 |
#define LDBL_MAX 1.18973149535723176502e+4932L |
#define LDBL_MAX_10_EXP 4932 |
#else |
/* same as IEEE double */ |
#define LDBL_MANT_DIG 53 |
#define LDBL_DIG 15 |
#define LDBL_EPSILON 2.2204460492503131e-16 |
#define LDBL_MIN_EXP (-1021) |
#define LDBL_MIN 2.2250738585072014e-308 |
#define LDBL_MIN_10_EXP (-307) |
#define LDBL_MAX_EXP 1024 |
#define LDBL_MAX 1.7976931348623157e+308 |
#define LDBL_MAX_10_EXP 308 |
#endif |
#endif /* _FLOAT_H_ */ |
/programs/develop/ktcc/trunk/source/include/stdarg.h |
---|
0,0 → 1,75 |
#ifndef _STDARG_H |
#define _STDARG_H |
#ifdef __x86_64__ |
#ifndef _WIN64 |
//This should be in sync with the declaration on our lib/libtcc1.c |
/* GCC compatible definition of va_list. */ |
typedef struct { |
unsigned int gp_offset; |
unsigned int fp_offset; |
union { |
unsigned int overflow_offset; |
char *overflow_arg_area; |
}; |
char *reg_save_area; |
} __va_list_struct; |
typedef __va_list_struct va_list[1]; |
void __va_start(__va_list_struct *ap, void *fp); |
void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align); |
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0)) |
#define va_arg(ap, type) \ |
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type)))) |
#define va_copy(dest, src) (*(dest) = *(src)) |
#define va_end(ap) |
#else /* _WIN64 */ |
typedef char *va_list; |
#define va_start(ap,last) __builtin_va_start(ap,last) |
#define va_arg(ap,type) (ap += 8, sizeof(type)<=8 ? *(type*)ap : **(type**)ap) |
#define va_copy(dest, src) ((dest) = (src)) |
#define va_end(ap) |
#endif |
#elif __arm__ |
typedef char *va_list; |
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x) |
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \ |
& ~(_tcc_alignof(type) - 1)) |
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3) |
#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \ |
&~3), *(type *)(ap - ((sizeof(type)+3)&~3))) |
#define va_copy(dest, src) (dest) = (src) |
#define va_end(ap) |
#elif defined(__aarch64__) |
typedef struct { |
void *__stack; |
void *__gr_top; |
void *__vr_top; |
int __gr_offs; |
int __vr_offs; |
} va_list; |
#define va_start(ap, last) __va_start(ap, last) |
#define va_arg(ap, type) __va_arg(ap, type) |
#define va_end(ap) |
#define va_copy(dest, src) ((dest) = (src)) |
#else /* __i386__ */ |
typedef char *va_list; |
/* only correct for i386 */ |
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3) |
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3))) |
#define va_copy(dest, src) (dest) = (src) |
#define va_end(ap) |
#endif |
/* fix a buggy dependency on GCC in libio.h */ |
typedef va_list __gnuc_va_list; |
#define _VA_LIST_DEFINED |
#endif /* _STDARG_H */ |
/programs/develop/ktcc/trunk/source/include/stdbool.h |
---|
0,0 → 1,11 |
#ifndef _STDBOOL_H |
#define _STDBOOL_H |
/* ISOC99 boolean */ |
#define bool _Bool |
#define true 1 |
#define false 0 |
#define __bool_true_false_are_defined 1 |
#endif /* _STDBOOL_H */ |
/programs/develop/ktcc/trunk/source/include/stddef.h |
---|
0,0 → 1,46 |
#ifndef _STDDEF_H |
#define _STDDEF_H |
typedef __SIZE_TYPE__ size_t; |
typedef __PTRDIFF_TYPE__ ssize_t; |
typedef __WCHAR_TYPE__ wchar_t; |
typedef __PTRDIFF_TYPE__ ptrdiff_t; |
typedef __PTRDIFF_TYPE__ intptr_t; |
typedef __SIZE_TYPE__ uintptr_t; |
#ifndef __int8_t_defined |
#define __int8_t_defined |
typedef signed char int8_t; |
typedef signed short int int16_t; |
typedef signed int int32_t; |
typedef signed long long int int64_t; |
typedef unsigned char uint8_t; |
typedef unsigned short int uint16_t; |
typedef unsigned int uint32_t; |
typedef unsigned long long int uint64_t; |
#endif |
#ifndef NULL |
#define NULL ((void*)0) |
#endif |
#define offsetof(type, field) ((size_t)&((type *)0)->field) |
void *alloca(size_t size); |
#endif |
/* Older glibc require a wint_t from <stddef.h> (when requested |
by __need_wint_t, as otherwise stddef.h isn't allowed to |
define this type). Note that this must be outside the normal |
_STDDEF_H guard, so that it works even when we've included the file |
already (without requiring wint_t). Some other libs define _WINT_T |
if they've already provided that type, so we can use that as guard. |
TCC defines __WINT_TYPE__ for us. */ |
#if defined (__need_wint_t) |
#ifndef _WINT_T |
#define _WINT_T |
typedef __WINT_TYPE__ wint_t; |
#endif |
#undef __need_wint_t |
#endif |
/programs/develop/ktcc/trunk/source/include/varargs.h |
---|
0,0 → 1,12 |
/** |
* This file has no copyright assigned and is placed in the Public Domain. |
* This file is part of the w64 mingw-runtime package. |
* No warranty is given; refer to the file DISCLAIMER within this package. |
*/ |
#ifndef _VARARGS_H |
#define _VARARGS_H |
#error "TinyCC no longer implements <varargs.h>." |
#error "Revise your code to use <stdarg.h>." |
#endif |
/programs/develop/ktcc/trunk/source/lib/Makefile |
---|
0,0 → 1,128 |
# |
# Tiny C Compiler Makefile for libtcc1.a |
# |
TOP = .. |
include $(TOP)/Makefile |
VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib |
ifndef TARGET # native library |
ifdef CONFIG_WIN64 |
TARGET = x86_64-win |
else |
ifdef CONFIG_WIN32 |
TARGET = i386-win |
else |
ifeq ($(ARCH),i386) |
TARGET = i386 |
else |
ifeq ($(ARCH),x86-64) |
TARGET = x86_64 |
else |
ifeq ($(ARCH),arm) |
TARGET = arm |
XCC = $(CC) |
else |
ifeq ($(ARCH),arm64) |
TARGET = arm64 |
else |
endif |
endif |
endif |
endif |
endif |
endif |
endif |
BCHECK_O = bcheck.o |
DIR = $(TARGET) |
native : ../libtcc1.a |
cross : $(DIR)/libtcc1.a |
native : TCC = $(TOP)/tcc$(EXESUF) |
cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF) |
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) |
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O) |
ARM_O = libtcc1.o armeabi.o alloca-arm.o |
WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o |
WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o |
ARM64_O = lib-arm64.o |
# build TCC runtime library to contain PIC code, so it can be linked |
# into shared libraries |
PICFLAGS = -fPIC |
# don't compile with -fstack-protector-strong, TCC doesn't handle it |
# correctly |
CFLAGS := $(filter-out -fstack-protector-strong,$(CFLAGS)) |
ifeq "$(TARGET)" "i386-win" |
OBJ = $(addprefix $(DIR)/,$(WIN32_O)) |
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE |
XCC ?= $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include |
XAR ?= $(DIR)/tiny_libmaker$(EXESUF) |
PICFLAGS = |
else |
ifeq "$(TARGET)" "x86_64-win" |
OBJ = $(addprefix $(DIR)/,$(WIN64_O)) |
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE |
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include |
XAR ?= $(DIR)/tiny_libmaker$(EXESUF) |
PICFLAGS = |
else |
ifeq "$(TARGET)" "i386" |
OBJ = $(addprefix $(DIR)/,$(I386_O)) |
TGT = -DTCC_TARGET_I386 |
XCC ?= $(TCC) -B$(TOP) |
else |
ifeq "$(TARGET)" "x86_64" |
OBJ = $(addprefix $(DIR)/,$(X86_64_O)) |
TGT = -DTCC_TARGET_X86_64 |
XCC ?= $(TCC) -B$(TOP) |
else |
ifeq "$(TARGET)" "arm" |
OBJ = $(addprefix $(DIR)/,$(ARM_O)) |
TGT = -DTCC_TARGET_ARM |
XCC ?= $(TCC) -B$(TOP) |
else |
ifeq "$(TARGET)" "arm64" |
OBJ = $(addprefix $(DIR)/,$(ARM64_O)) |
TGT = -DTCC_TARGET_ARM64 |
XCC ?= $(TCC) -B$(TOP) |
else |
$(error libtcc1.a not supported on target '$(TARGET)') |
endif |
endif |
endif |
endif |
endif |
endif |
XFLAGS = $(filter-out -b,$(CPPFLAGS) $(CFLAGS) $(PICFLAGS) $(TGT)) |
ifeq ($(TARGETOS),Darwin) |
XAR = $(DIR)/tiny_libmaker$(EXESUF) |
XFLAGS += -D_ANSI_SOURCE |
BCHECK_O = |
endif |
XAR ?= $(AR) |
$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR) |
$(XAR) rcs $@ $(OBJ) |
$(DIR)/%.o : %.c |
$(XCC) -c $< -o $@ $(XFLAGS) |
$(DIR)/%.o : %.S |
$(XCC) -c $< -o $@ $(XFLAGS) |
$(DIR)/%$(EXESUF) : $(TOP)/win32/tools/%.c |
$(CC) -o $@ $< $(XFLAGS) $(LDFLAGS) |
$(OBJ) $(XAR) : $(DIR)/exists |
$(DIR)/exists : |
mkdir -p $(DIR) |
@echo $@ > $@ |
clean : |
rm -rfv i386-win x86_64-win i386 x86_64 arm64 |
/programs/develop/ktcc/trunk/source/lib/alloca-arm.S |
---|
0,0 → 1,11 |
.text |
.align 2 |
.global alloca |
.type alloca, %function |
alloca: |
rsb sp, r0, sp |
bic sp, sp, #7 |
mov r0, sp |
mov pc, lr |
.size alloca, .-alloca |
.section .note.GNU-stack,"",%progbits |
/programs/develop/ktcc/trunk/source/lib/alloca86-bt.S |
---|
0,0 → 1,47 |
/* ---------------------------------------------- */ |
/* alloca86-bt.S */ |
.globl __bound_alloca |
__bound_alloca: |
pop %edx |
pop %eax |
mov %eax, %ecx |
add $3,%eax |
and $-4,%eax |
jz p6 |
#ifdef TCC_TARGET_PE |
p4: |
cmp $4096,%eax |
jbe p5 |
test %eax,-4096(%esp) |
sub $4096,%esp |
sub $4096,%eax |
jmp p4 |
p5: |
#endif |
sub %eax,%esp |
mov %esp,%eax |
push %edx |
push %eax |
push %ecx |
push %eax |
call __bound_new_region |
add $8, %esp |
pop %eax |
pop %edx |
p6: |
push %edx |
push %edx |
ret |
/* mark stack as nonexecutable */ |
#if defined __ELF__ && defined __linux__ |
.section .note.GNU-stack,"",@progbits |
#endif |
/* ---------------------------------------------- */ |
/programs/develop/ktcc/trunk/source/lib/alloca86.S |
---|
0,0 → 1,35 |
/* ---------------------------------------------- */ |
/* alloca86.S */ |
.globl alloca |
alloca: |
pop %edx |
pop %eax |
add $3,%eax |
and $-4,%eax |
jz p3 |
#ifdef TCC_TARGET_PE |
p1: |
cmp $4096,%eax |
jbe p2 |
test %eax,-4096(%esp) |
sub $4096,%esp |
sub $4096,%eax |
jmp p1 |
p2: |
#endif |
sub %eax,%esp |
mov %esp,%eax |
p3: |
push %edx |
push %edx |
ret |
/* mark stack as nonexecutable */ |
#if defined __ELF__ && defined __linux__ |
.section .note.GNU-stack,"",@progbits |
#endif |
/* ---------------------------------------------- */ |
/programs/develop/ktcc/trunk/source/lib/alloca86_64-bt.S |
---|
0,0 → 1,60 |
/* ---------------------------------------------- */ |
/* alloca86_64.S */ |
.globl __bound_alloca |
__bound_alloca: |
#ifdef TCC_TARGET_PE |
# bound checking is not implemented |
pop %rdx |
mov %rcx,%rax |
add $15,%rax |
and $-16,%rax |
jz p3 |
p1: |
cmp $4096,%rax |
jbe p2 |
test %rax,-4096(%rsp) |
sub $4096,%rsp |
sub $4096,%rax |
jmp p1 |
p2: |
sub %rax,%rsp |
mov %rsp,%rax |
add $32,%rax |
p3: |
push %rdx |
ret |
#else |
pop %rdx |
mov %rdi,%rax |
movl %rax,%rsi # size, a second parm to the __bound_new_region |
add $15,%rax |
and $-16,%rax |
jz p3 |
sub %rax,%rsp |
mov %rsp,%rdi # pointer, a first parm to the __bound_new_region |
mov %rsp,%rax |
push %rdx |
push %rax |
call __bound_new_region |
pop %rax |
pop %rdx |
p3: |
push %rdx |
ret |
#endif |
/* mark stack as nonexecutable */ |
#if defined __ELF__ && defined __linux__ |
.section .note.GNU-stack,"",@progbits |
#endif |
/* ---------------------------------------------- */ |
/programs/develop/ktcc/trunk/source/lib/alloca86_64.S |
---|
0,0 → 1,42 |
/* ---------------------------------------------- */ |
/* alloca86_64.S */ |
.globl alloca |
alloca: |
pop %rdx |
#ifdef TCC_TARGET_PE |
mov %rcx,%rax |
#else |
mov %rdi,%rax |
#endif |
add $15,%rax |
and $-16,%rax |
jz p3 |
#ifdef TCC_TARGET_PE |
p1: |
cmp $4096,%rax |
jbe p2 |
test %rax,-4096(%rsp) |
sub $4096,%rsp |
sub $4096,%rax |
jmp p1 |
p2: |
#endif |
sub %rax,%rsp |
mov %rsp,%rax |
#ifdef TCC_TARGET_PE |
add $32,%rax |
#endif |
p3: |
push %rdx |
ret |
/* mark stack as nonexecutable */ |
#if defined __ELF__ && defined __linux__ |
.section .note.GNU-stack,"",@progbits |
#endif |
/* ---------------------------------------------- */ |
/programs/develop/ktcc/trunk/source/lib/armeabi.c |
---|
0,0 → 1,489 |
/* TCC ARM runtime EABI |
Copyright (C) 2013 Thomas Preud'homme |
Permission is hereby granted, free of charge, to any person obtaining a copy |
of this software and associated documentation files (the "Software"), to deal |
in the Software without restriction, including without limitation the rights |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
copies of the Software, and to permit persons to whom the Software is |
furnished to do so, subject to the following conditions: |
The above copyright notice and this permission notice shall be included in |
all copies or substantial portions of the software. |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
THE SOFTWARE.*/ |
#include <limits.h> |
/* We rely on the little endianness and EABI calling convention for this to |
work */ |
typedef struct double_unsigned_struct { |
unsigned low; |
unsigned high; |
} double_unsigned_struct; |
typedef struct unsigned_int_struct { |
unsigned low; |
int high; |
} unsigned_int_struct; |
#define REGS_RETURN(name, type) \ |
void name ## _return(type ret) {} |
/* Float helper functions */ |
#define FLOAT_EXP_BITS 8 |
#define FLOAT_FRAC_BITS 23 |
#define DOUBLE_EXP_BITS 11 |
#define DOUBLE_FRAC_BITS 52 |
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1) |
REGS_RETURN(unsigned_int_struct, unsigned_int_struct) |
REGS_RETURN(double_unsigned_struct, double_unsigned_struct) |
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */ |
/* float to [unsigned] long long conversion */ |
#define DEFINE__AEABI_F2XLZ(name, with_sign) \ |
void __aeabi_ ## name(unsigned val) \ |
{ \ |
int exp, high_shift, sign; \ |
double_unsigned_struct ret; \ |
\ |
/* compute sign */ \ |
sign = val >> 31; \ |
\ |
/* compute real exponent */ \ |
exp = val >> FLOAT_FRAC_BITS; \ |
exp &= (1 << FLOAT_EXP_BITS) - 1; \ |
exp -= ONE_EXP(FLOAT); \ |
\ |
/* undefined behavior if truncated value cannot be represented */ \ |
if (with_sign) { \ |
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \ |
return; \ |
} else { \ |
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \ |
return; \ |
} \ |
\ |
val &= (1 << FLOAT_FRAC_BITS) - 1; \ |
if (exp >= 32) { \ |
ret.high = 1 << (exp - 32); \ |
if (exp - 32 >= FLOAT_FRAC_BITS) { \ |
ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \ |
ret.low = 0; \ |
} else { \ |
high_shift = FLOAT_FRAC_BITS - (exp - 32); \ |
ret.high |= val >> high_shift; \ |
ret.low = val << (32 - high_shift); \ |
} \ |
} else { \ |
ret.high = 0; \ |
ret.low = 1 << exp; \ |
if (exp > FLOAT_FRAC_BITS) \ |
ret.low |= val << (exp - FLOAT_FRAC_BITS); \ |
else \ |
ret.low |= val >> (FLOAT_FRAC_BITS - exp); \ |
} \ |
\ |
/* encode negative integer using 2's complement */ \ |
if (with_sign && sign) { \ |
ret.low = ~ret.low; \ |
ret.high = ~ret.high; \ |
if (ret.low == UINT_MAX) { \ |
ret.low = 0; \ |
ret.high++; \ |
} else \ |
ret.low++; \ |
} \ |
\ |
double_unsigned_struct_return(ret); \ |
} |
/* float to unsigned long long conversion */ |
DEFINE__AEABI_F2XLZ(f2ulz, 0) |
/* float to long long conversion */ |
DEFINE__AEABI_F2XLZ(f2lz, 1) |
/* double to [unsigned] long long conversion */ |
#define DEFINE__AEABI_D2XLZ(name, with_sign) \ |
void __aeabi_ ## name(double_unsigned_struct val) \ |
{ \ |
int exp, high_shift, sign; \ |
double_unsigned_struct ret; \ |
\ |
/* compute sign */ \ |
sign = val.high >> 31; \ |
\ |
/* compute real exponent */ \ |
exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \ |
exp &= (1 << DOUBLE_EXP_BITS) - 1; \ |
exp -= ONE_EXP(DOUBLE); \ |
\ |
/* undefined behavior if truncated value cannot be represented */ \ |
if (with_sign) { \ |
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \ |
return; \ |
} else { \ |
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \ |
return; \ |
} \ |
\ |
val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \ |
if (exp >= 32) { \ |
ret.high = 1 << (exp - 32); \ |
if (exp >= DOUBLE_FRAC_BITS) { \ |
high_shift = exp - DOUBLE_FRAC_BITS; \ |
ret.high |= val.high << high_shift; \ |
ret.high |= val.low >> (32 - high_shift); \ |
ret.low = val.low << high_shift; \ |
} else { \ |
high_shift = DOUBLE_FRAC_BITS - exp; \ |
ret.high |= val.high >> high_shift; \ |
ret.low = val.high << (32 - high_shift); \ |
ret.low |= val.low >> high_shift; \ |
} \ |
} else { \ |
ret.high = 0; \ |
ret.low = 1 << exp; \ |
if (exp > DOUBLE_FRAC_BITS - 32) { \ |
high_shift = exp - DOUBLE_FRAC_BITS - 32; \ |
ret.low |= val.high << high_shift; \ |
ret.low |= val.low >> (32 - high_shift); \ |
} else \ |
ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \ |
} \ |
\ |
/* encode negative integer using 2's complement */ \ |
if (with_sign && sign) { \ |
ret.low = ~ret.low; \ |
ret.high = ~ret.high; \ |
if (ret.low == UINT_MAX) { \ |
ret.low = 0; \ |
ret.high++; \ |
} else \ |
ret.low++; \ |
} \ |
\ |
double_unsigned_struct_return(ret); \ |
} |
/* double to unsigned long long conversion */ |
DEFINE__AEABI_D2XLZ(d2ulz, 0) |
/* double to long long conversion */ |
DEFINE__AEABI_D2XLZ(d2lz, 1) |
/* long long to float conversion */ |
#define DEFINE__AEABI_XL2F(name, with_sign) \ |
unsigned __aeabi_ ## name(unsigned long long v) \ |
{ \ |
int s /* shift */, flb /* first lost bit */, sign = 0; \ |
unsigned p = 0 /* power */, ret; \ |
double_unsigned_struct val; \ |
\ |
/* fraction in negative float is encoded in 1's complement */ \ |
if (with_sign && (v & (1ULL << 63))) { \ |
sign = 1; \ |
v = ~v + 1; \ |
} \ |
val.low = v; \ |
val.high = v >> 32; \ |
/* fill fraction bits */ \ |
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \ |
if (p) { \ |
ret = val.high & (p - 1); \ |
if (s < FLOAT_FRAC_BITS) { \ |
ret <<= FLOAT_FRAC_BITS - s; \ |
ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \ |
flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \ |
} else { \ |
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \ |
ret >>= s - FLOAT_FRAC_BITS; \ |
} \ |
s += 32; \ |
} else { \ |
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \ |
if (p) { \ |
ret = val.low & (p - 1); \ |
if (s <= FLOAT_FRAC_BITS) { \ |
ret <<= FLOAT_FRAC_BITS - s; \ |
flb = 0; \ |
} else { \ |
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \ |
ret >>= s - FLOAT_FRAC_BITS; \ |
} \ |
} else \ |
return 0; \ |
} \ |
if (flb) \ |
ret++; \ |
\ |
/* fill exponent bits */ \ |
ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \ |
\ |
/* fill sign bit */ \ |
ret |= sign << 31; \ |
\ |
return ret; \ |
} |
/* unsigned long long to float conversion */ |
DEFINE__AEABI_XL2F(ul2f, 0) |
/* long long to float conversion */ |
DEFINE__AEABI_XL2F(l2f, 1) |
/* long long to double conversion */ |
#define __AEABI_XL2D(name, with_sign) \ |
void __aeabi_ ## name(unsigned long long v) \ |
{ \ |
int s /* shift */, high_shift, sign = 0; \ |
unsigned tmp, p = 0; \ |
double_unsigned_struct val, ret; \ |
\ |
/* fraction in negative float is encoded in 1's complement */ \ |
if (with_sign && (v & (1ULL << 63))) { \ |
sign = 1; \ |
v = ~v + 1; \ |
} \ |
val.low = v; \ |
val.high = v >> 32; \ |
\ |
/* fill fraction bits */ \ |
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \ |
if (p) { \ |
tmp = val.high & (p - 1); \ |
if (s < DOUBLE_FRAC_BITS - 32) { \ |
high_shift = DOUBLE_FRAC_BITS - 32 - s; \ |
ret.high = tmp << high_shift; \ |
ret.high |= val.low >> (32 - high_shift); \ |
ret.low = val.low << high_shift; \ |
} else { \ |
high_shift = s - (DOUBLE_FRAC_BITS - 32); \ |
ret.high = tmp >> high_shift; \ |
ret.low = tmp << (32 - high_shift); \ |
ret.low |= val.low >> high_shift; \ |
if ((val.low >> (high_shift - 1)) & 1) { \ |
if (ret.low == UINT_MAX) { \ |
ret.high++; \ |
ret.low = 0; \ |
} else \ |
ret.low++; \ |
} \ |
} \ |
s += 32; \ |
} else { \ |
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \ |
if (p) { \ |
tmp = val.low & (p - 1); \ |
if (s <= DOUBLE_FRAC_BITS - 32) { \ |
high_shift = DOUBLE_FRAC_BITS - 32 - s; \ |
ret.high = tmp << high_shift; \ |
ret.low = 0; \ |
} else { \ |
high_shift = s - (DOUBLE_FRAC_BITS - 32); \ |
ret.high = tmp >> high_shift; \ |
ret.low = tmp << (32 - high_shift); \ |
} \ |
} else { \ |
ret.high = ret.low = 0; \ |
double_unsigned_struct_return(ret); \ |
} \ |
} \ |
\ |
/* fill exponent bits */ \ |
ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \ |
\ |
/* fill sign bit */ \ |
ret.high |= sign << 31; \ |
\ |
double_unsigned_struct_return(ret); \ |
} |
/* unsigned long long to double conversion */ |
__AEABI_XL2D(ul2d, 0) |
/* long long to double conversion */ |
__AEABI_XL2D(l2d, 1) |
/* Long long helper functions */ |
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */ |
#define define_aeabi_xdivmod_signed_type(basetype, type) \ |
typedef struct type { \ |
basetype quot; \ |
unsigned basetype rem; \ |
} type |
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \ |
typedef struct type { \ |
basetype quot; \ |
basetype rem; \ |
} type |
#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \ |
static inline rettype aeabi_ ## name (type num, type den) \ |
{ \ |
rettype ret; \ |
type quot = 0; \ |
\ |
/* Increase quotient while it is less than numerator */ \ |
while (num >= den) { \ |
type q = 1; \ |
\ |
/* Find closest power of two */ \ |
while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \ |
q <<= 1; \ |
\ |
/* Compute difference between current quotient and numerator */ \ |
num -= q * den; \ |
quot += q; \ |
} \ |
ret.quot = quot; \ |
ret.rem = num; \ |
return ret; \ |
} |
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \ |
void __aeabi_ ## name(type numerator, type denominator) \ |
{ \ |
unsigned type num, den; \ |
urettype uxdiv_ret; \ |
rettype ret; \ |
\ |
if (numerator >= 0) \ |
num = numerator; \ |
else \ |
num = 0 - numerator; \ |
if (denominator >= 0) \ |
den = denominator; \ |
else \ |
den = 0 - denominator; \ |
uxdiv_ret = aeabi_ ## uiname(num, den); \ |
/* signs differ */ \ |
if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \ |
ret.quot = 0 - uxdiv_ret.quot; \ |
else \ |
ret.quot = uxdiv_ret.quot; \ |
if (numerator < 0) \ |
ret.rem = 0 - uxdiv_ret.rem; \ |
else \ |
ret.rem = uxdiv_ret.rem; \ |
\ |
rettype ## _return(ret); \ |
} |
define_aeabi_xdivmod_signed_type(long long, lldiv_t); |
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t); |
define_aeabi_xdivmod_signed_type(int, idiv_t); |
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t); |
REGS_RETURN(lldiv_t, lldiv_t) |
REGS_RETURN(ulldiv_t, ulldiv_t) |
REGS_RETURN(idiv_t, idiv_t) |
REGS_RETURN(uidiv_t, uidiv_t) |
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG) |
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG) |
void __aeabi_uldivmod(unsigned long long num, unsigned long long den) |
{ |
ulldiv_t_return(aeabi_uldivmod(num, den)); |
} |
void __aeabi_llsl(double_unsigned_struct val, int shift) |
{ |
double_unsigned_struct ret; |
if (shift >= 32) { |
val.high = val.low; |
val.low = 0; |
shift -= 32; |
} |
if (shift > 0) { |
ret.low = val.low << shift; |
ret.high = (val.high << shift) | (val.low >> (32 - shift)); |
double_unsigned_struct_return(ret); |
return; |
} |
double_unsigned_struct_return(val); |
} |
#define aeabi_lsr(val, shift, fill, type) \ |
type ## _struct ret; \ |
\ |
if (shift >= 32) { \ |
val.low = val.high; \ |
val.high = fill; \ |
shift -= 32; \ |
} \ |
if (shift > 0) { \ |
ret.high = val.high >> shift; \ |
ret.low = (val.high << (32 - shift)) | (val.low >> shift); \ |
type ## _struct_return(ret); \ |
return; \ |
} \ |
type ## _struct_return(val); |
void __aeabi_llsr(double_unsigned_struct val, int shift) |
{ |
aeabi_lsr(val, shift, 0, double_unsigned); |
} |
void __aeabi_lasr(unsigned_int_struct val, int shift) |
{ |
aeabi_lsr(val, shift, val.high >> 31, unsigned_int); |
} |
/* Integer division functions */ |
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT) |
int __aeabi_idiv(int numerator, int denominator) |
{ |
unsigned num, den; |
uidiv_t ret; |
if (numerator >= 0) |
num = numerator; |
else |
num = 0 - numerator; |
if (denominator >= 0) |
den = denominator; |
else |
den = 0 - denominator; |
ret = aeabi_uidivmod(num, den); |
if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */ |
ret.quot *= -1; |
return ret.quot; |
} |
unsigned __aeabi_uidiv(unsigned num, unsigned den) |
{ |
return aeabi_uidivmod(num, den).quot; |
} |
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT) |
void __aeabi_uidivmod(unsigned num, unsigned den) |
{ |
uidiv_t_return(aeabi_uidivmod(num, den)); |
} |
/programs/develop/ktcc/trunk/source/lib/bcheck.c |
---|
0,0 → 1,950 |
/* |
* Tiny C Memory and bounds checker |
* |
* Copyright (c) 2002 Fabrice Bellard |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
#include <stdlib.h> |
#include <stdio.h> |
#include <stdarg.h> |
#include <string.h> |
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) \ |
&& !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) |
#include <malloc.h> |
#endif |
#if !defined(_WIN32) |
#include <unistd.h> |
#endif |
/* #define BOUND_DEBUG */ |
#ifdef BOUND_DEBUG |
#define dprintf(a...) fprintf(a) |
#else |
#define dprintf(a...) |
#endif |
/* define so that bound array is static (faster, but use memory if |
bound checking not used) */ |
/* #define BOUND_STATIC */ |
/* use malloc hooks. Currently the code cannot be reliable if no hooks */ |
#define CONFIG_TCC_MALLOC_HOOKS |
#define HAVE_MEMALIGN |
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ |
|| defined(__DragonFly__) || defined(__dietlibc__) \ |
|| defined(__UCLIBC__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
|| defined(_WIN32) || defined(TCC_UCLIBC) |
#warning Bound checking does not support malloc (etc.) in this environment. |
#undef CONFIG_TCC_MALLOC_HOOKS |
#undef HAVE_MEMALIGN |
#endif |
#define BOUND_T1_BITS 13 |
#define BOUND_T2_BITS 11 |
#define BOUND_T3_BITS (sizeof(size_t)*8 - BOUND_T1_BITS - BOUND_T2_BITS) |
#define BOUND_E_BITS (sizeof(size_t)) |
#define BOUND_T1_SIZE (1 << BOUND_T1_BITS) |
#define BOUND_T2_SIZE (1 << BOUND_T2_BITS) |
#define BOUND_T3_SIZE (1 << BOUND_T3_BITS) |
#define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS) |
#define BOUND_T23_SIZE (1 << BOUND_T23_BITS) |
/* this pointer is generated when bound check is incorrect */ |
#define INVALID_POINTER ((void *)(-2)) |
/* size of an empty region */ |
#define EMPTY_SIZE ((size_t)(-1)) |
/* size of an invalid region */ |
#define INVALID_SIZE 0 |
typedef struct BoundEntry { |
size_t start; |
size_t size; |
struct BoundEntry *next; |
size_t is_invalid; /* true if pointers outside region are invalid */ |
} BoundEntry; |
/* external interface */ |
void __bound_init(void); |
void __bound_new_region(void *p, size_t size); |
int __bound_delete_region(void *p); |
#ifdef __attribute__ |
/* an __attribute__ macro is defined in the system headers */ |
#undef __attribute__ |
#endif |
#define FASTCALL __attribute__((regparm(3))) |
void *__bound_malloc(size_t size, const void *caller); |
void *__bound_memalign(size_t size, size_t align, const void *caller); |
void __bound_free(void *ptr, const void *caller); |
void *__bound_realloc(void *ptr, size_t size, const void *caller); |
static void *libc_malloc(size_t size); |
static void libc_free(void *ptr); |
static void install_malloc_hooks(void); |
static void restore_malloc_hooks(void); |
#ifdef CONFIG_TCC_MALLOC_HOOKS |
static void *saved_malloc_hook; |
static void *saved_free_hook; |
static void *saved_realloc_hook; |
static void *saved_memalign_hook; |
#endif |
/* TCC definitions */ |
extern char __bounds_start; /* start of static bounds table */ |
/* error message, just for TCC */ |
const char *__bound_error_msg; |
/* runtime error output */ |
extern void rt_error(size_t pc, const char *fmt, ...); |
#ifdef BOUND_STATIC |
static BoundEntry *__bound_t1[BOUND_T1_SIZE]; /* page table */ |
#else |
static BoundEntry **__bound_t1; /* page table */ |
#endif |
static BoundEntry *__bound_empty_t2; /* empty page, for unused pages */ |
static BoundEntry *__bound_invalid_t2; /* invalid page, for invalid pointers */ |
static BoundEntry *__bound_find_region(BoundEntry *e1, void *p) |
{ |
size_t addr, tmp; |
BoundEntry *e; |
e = e1; |
while (e != NULL) { |
addr = (size_t)p; |
addr -= e->start; |
if (addr <= e->size) { |
/* put region at the head */ |
tmp = e1->start; |
e1->start = e->start; |
e->start = tmp; |
tmp = e1->size; |
e1->size = e->size; |
e->size = tmp; |
return e1; |
} |
e = e->next; |
} |
/* no entry found: return empty entry or invalid entry */ |
if (e1->is_invalid) |
return __bound_invalid_t2; |
else |
return __bound_empty_t2; |
} |
/* print a bound error message */ |
static void bound_error(const char *fmt, ...) |
{ |
__bound_error_msg = fmt; |
fprintf(stderr,"%s %s: %s\n", __FILE__, __FUNCTION__, fmt); |
*(int *)0 = 0; /* force a runtime error */ |
} |
static void bound_alloc_error(void) |
{ |
bound_error("not enough memory for bound checking code"); |
} |
/* return '(p + offset)' for pointer arithmetic (a pointer can reach |
the end of a region in this case */ |
void * FASTCALL __bound_ptr_add(void *p, size_t offset) |
{ |
size_t addr = (size_t)p; |
BoundEntry *e; |
__bound_init(); |
dprintf(stderr, "%s %s: %p %p\n", __FILE__, __FUNCTION__, p, offset); |
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; |
e = (BoundEntry *)((char *)e + |
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); |
addr -= e->start; |
if (addr > e->size) { |
e = __bound_find_region(e, p); |
addr = (size_t)p - e->start; |
} |
addr += offset; |
if (addr >= e->size) { |
fprintf(stderr,"%s %s: %p is outside of the region\n", __FILE__, __FUNCTION__, p + offset); |
return INVALID_POINTER; /* return an invalid pointer */ |
} |
return p + offset; |
} |
/* return '(p + offset)' for pointer indirection (the resulting must |
be strictly inside the region */ |
#define BOUND_PTR_INDIR(dsize) \ |
void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ |
{ \ |
size_t addr = (size_t)p; \ |
BoundEntry *e; \ |
\ |
dprintf(stderr, "%s %s: %p %p start\n", __FILE__, __FUNCTION__, p, offset); \ |
\ |
__bound_init(); \ |
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \ |
e = (BoundEntry *)((char *)e + \ |
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & \ |
((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); \ |
addr -= e->start; \ |
if (addr > e->size) { \ |
e = __bound_find_region(e, p); \ |
addr = (size_t)p - e->start; \ |
} \ |
addr += offset + dsize; \ |
if (addr > e->size) { \ |
fprintf(stderr,"%s %s: %p is outside of the region\n", __FILE__, __FUNCTION__, p + offset); \ |
return INVALID_POINTER; /* return an invalid pointer */ \ |
} \ |
dprintf(stderr, "%s %s: return p+offset = %p\n", __FILE__, __FUNCTION__, p + offset); \ |
return p + offset; \ |
} |
BOUND_PTR_INDIR(1) |
BOUND_PTR_INDIR(2) |
BOUND_PTR_INDIR(4) |
BOUND_PTR_INDIR(8) |
BOUND_PTR_INDIR(12) |
BOUND_PTR_INDIR(16) |
/* return the frame pointer of the caller */ |
#define GET_CALLER_FP(fp)\ |
{\ |
fp = (size_t)__builtin_frame_address(1);\ |
} |
/* called when entering a function to add all the local regions */ |
void FASTCALL __bound_local_new(void *p1) |
{ |
size_t addr, size, fp, *p = p1; |
dprintf(stderr, "%s, %s start p1=%p\n", __FILE__, __FUNCTION__, p); |
GET_CALLER_FP(fp); |
for(;;) { |
addr = p[0]; |
if (addr == 0) |
break; |
addr += fp; |
size = p[1]; |
p += 2; |
__bound_new_region((void *)addr, size); |
} |
dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); |
} |
/* called when leaving a function to delete all the local regions */ |
void FASTCALL __bound_local_delete(void *p1) |
{ |
size_t addr, fp, *p = p1; |
GET_CALLER_FP(fp); |
for(;;) { |
addr = p[0]; |
if (addr == 0) |
break; |
addr += fp; |
p += 2; |
__bound_delete_region((void *)addr); |
} |
} |
static BoundEntry *__bound_new_page(void) |
{ |
BoundEntry *page; |
size_t i; |
page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE); |
if (!page) |
bound_alloc_error(); |
for(i=0;i<BOUND_T2_SIZE;i++) { |
/* put empty entries */ |
page[i].start = 0; |
page[i].size = EMPTY_SIZE; |
page[i].next = NULL; |
page[i].is_invalid = 0; |
} |
return page; |
} |
/* currently we use malloc(). Should use bound_new_page() */ |
static BoundEntry *bound_new_entry(void) |
{ |
BoundEntry *e; |
e = libc_malloc(sizeof(BoundEntry)); |
return e; |
} |
static void bound_free_entry(BoundEntry *e) |
{ |
libc_free(e); |
} |
static BoundEntry *get_page(size_t index) |
{ |
BoundEntry *page; |
page = __bound_t1[index]; |
if (!page || page == __bound_empty_t2 || page == __bound_invalid_t2) { |
/* create a new page if necessary */ |
page = __bound_new_page(); |
__bound_t1[index] = page; |
} |
return page; |
} |
/* mark a region as being invalid (can only be used during init) */ |
static void mark_invalid(size_t addr, size_t size) |
{ |
size_t start, end; |
BoundEntry *page; |
size_t t1_start, t1_end, i, j, t2_start, t2_end; |
start = addr; |
end = addr + size; |
t2_start = (start + BOUND_T3_SIZE - 1) >> BOUND_T3_BITS; |
if (end != 0) |
t2_end = end >> BOUND_T3_BITS; |
else |
t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS); |
#if 0 |
dprintf(stderr, "mark_invalid: start = %x %x\n", t2_start, t2_end); |
#endif |
/* first we handle full pages */ |
t1_start = (t2_start + BOUND_T2_SIZE - 1) >> BOUND_T2_BITS; |
t1_end = t2_end >> BOUND_T2_BITS; |
i = t2_start & (BOUND_T2_SIZE - 1); |
j = t2_end & (BOUND_T2_SIZE - 1); |
if (t1_start == t1_end) { |
page = get_page(t2_start >> BOUND_T2_BITS); |
for(; i < j; i++) { |
page[i].size = INVALID_SIZE; |
page[i].is_invalid = 1; |
} |
} else { |
if (i > 0) { |
page = get_page(t2_start >> BOUND_T2_BITS); |
for(; i < BOUND_T2_SIZE; i++) { |
page[i].size = INVALID_SIZE; |
page[i].is_invalid = 1; |
} |
} |
for(i = t1_start; i < t1_end; i++) { |
__bound_t1[i] = __bound_invalid_t2; |
} |
if (j != 0) { |
page = get_page(t1_end); |
for(i = 0; i < j; i++) { |
page[i].size = INVALID_SIZE; |
page[i].is_invalid = 1; |
} |
} |
} |
} |
void __bound_init(void) |
{ |
size_t i; |
BoundEntry *page; |
size_t start, size; |
size_t *p; |
static int inited; |
if (inited) |
return; |
inited = 1; |
dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); |
/* save malloc hooks and install bound check hooks */ |
install_malloc_hooks(); |
#ifndef BOUND_STATIC |
__bound_t1 = libc_malloc(BOUND_T1_SIZE * sizeof(BoundEntry *)); |
if (!__bound_t1) |
bound_alloc_error(); |
#endif |
__bound_empty_t2 = __bound_new_page(); |
for(i=0;i<BOUND_T1_SIZE;i++) { |
__bound_t1[i] = __bound_empty_t2; |
} |
page = __bound_new_page(); |
for(i=0;i<BOUND_T2_SIZE;i++) { |
/* put invalid entries */ |
page[i].start = 0; |
page[i].size = INVALID_SIZE; |
page[i].next = NULL; |
page[i].is_invalid = 1; |
} |
__bound_invalid_t2 = page; |
/* invalid pointer zone */ |
start = (size_t)INVALID_POINTER & ~(BOUND_T23_SIZE - 1); |
size = BOUND_T23_SIZE; |
mark_invalid(start, size); |
#if defined(CONFIG_TCC_MALLOC_HOOKS) |
/* malloc zone is also marked invalid. can only use that with |
* hooks because all libs should use the same malloc. The solution |
* would be to build a new malloc for tcc. |
* |
* usually heap (= malloc zone) comes right after bss, i.e. after _end, but |
* not always - either if we are running from under `tcc -b -run`, or if |
* address space randomization is turned on(a), heap start will be separated |
* from bss end. |
* |
* So sbrk(0) will be a good approximation for start_brk: |
* |
* - if we are a separately compiled program, __bound_init() runs early, |
* and sbrk(0) should be equal or very near to start_brk(b) (in case other |
* constructors malloc something), or |
* |
* - if we are running from under `tcc -b -run`, sbrk(0) will return |
* start of heap portion which is under this program control, and not |
* mark as invalid earlier allocated memory. |
* |
* |
* (a) /proc/sys/kernel/randomize_va_space = 2, on Linux; |
* usually turned on by default. |
* |
* (b) on Linux >= v3.3, the alternative is to read |
* start_brk from /proc/self/stat |
*/ |
start = (size_t)sbrk(0); |
size = 128 * 0x100000; |
mark_invalid(start, size); |
#endif |
/* add all static bound check values */ |
p = (size_t *)&__bounds_start; |
while (p[0] != 0) { |
__bound_new_region((void *)p[0], p[1]); |
p += 2; |
} |
dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); |
} |
void __bound_main_arg(void **p) |
{ |
void *start = p; |
while (*p++); |
dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", |
__FILE__, __FUNCTION__, (void *) p - start); |
__bound_new_region(start, (void *) p - start); |
} |
void __bound_exit(void) |
{ |
restore_malloc_hooks(); |
} |
static inline void add_region(BoundEntry *e, |
size_t start, size_t size) |
{ |
BoundEntry *e1; |
if (e->start == 0) { |
/* no region : add it */ |
e->start = start; |
e->size = size; |
} else { |
/* already regions in the list: add it at the head */ |
e1 = bound_new_entry(); |
e1->start = e->start; |
e1->size = e->size; |
e1->next = e->next; |
e->start = start; |
e->size = size; |
e->next = e1; |
} |
} |
/* create a new region. It should not already exist in the region list */ |
void __bound_new_region(void *p, size_t size) |
{ |
size_t start, end; |
BoundEntry *page, *e, *e2; |
size_t t1_start, t1_end, i, t2_start, t2_end; |
__bound_init(); |
dprintf(stderr, "%s, %s(%p, %p) start\n", |
__FILE__, __FUNCTION__, p, size); |
start = (size_t)p; |
end = start + size; |
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); |
t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS); |
/* start */ |
page = get_page(t1_start); |
t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
e = (BoundEntry *)((char *)page + t2_start); |
add_region(e, start, size); |
if (t1_end == t1_start) { |
/* same ending page */ |
e2 = (BoundEntry *)((char *)page + t2_end); |
if (e2 > e) { |
e++; |
for(;e<e2;e++) { |
e->start = start; |
e->size = size; |
} |
add_region(e, start, size); |
} |
} else { |
/* mark until end of page */ |
e2 = page + BOUND_T2_SIZE; |
e++; |
for(;e<e2;e++) { |
e->start = start; |
e->size = size; |
} |
/* mark intermediate pages, if any */ |
for(i=t1_start+1;i<t1_end;i++) { |
page = get_page(i); |
e2 = page + BOUND_T2_SIZE; |
for(e=page;e<e2;e++) { |
e->start = start; |
e->size = size; |
} |
} |
/* last page */ |
page = get_page(t1_end); |
e2 = (BoundEntry *)((char *)page + t2_end); |
for(e=page;e<e2;e++) { |
e->start = start; |
e->size = size; |
} |
add_region(e, start, size); |
} |
dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); |
} |
/* delete a region */ |
static inline void delete_region(BoundEntry *e, |
void *p, size_t empty_size) |
{ |
size_t addr; |
BoundEntry *e1; |
addr = (size_t)p; |
addr -= e->start; |
if (addr <= e->size) { |
/* region found is first one */ |
e1 = e->next; |
if (e1 == NULL) { |
/* no more region: mark it empty */ |
e->start = 0; |
e->size = empty_size; |
} else { |
/* copy next region in head */ |
e->start = e1->start; |
e->size = e1->size; |
e->next = e1->next; |
bound_free_entry(e1); |
} |
} else { |
/* find the matching region */ |
for(;;) { |
e1 = e; |
e = e->next; |
/* region not found: do nothing */ |
if (e == NULL) |
break; |
addr = (size_t)p - e->start; |
if (addr <= e->size) { |
/* found: remove entry */ |
e1->next = e->next; |
bound_free_entry(e); |
break; |
} |
} |
} |
} |
/* WARNING: 'p' must be the starting point of the region. */ |
/* return non zero if error */ |
int __bound_delete_region(void *p) |
{ |
size_t start, end, addr, size, empty_size; |
BoundEntry *page, *e, *e2; |
size_t t1_start, t1_end, t2_start, t2_end, i; |
__bound_init(); |
dprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__); |
start = (size_t)p; |
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); |
t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
/* find region size */ |
page = __bound_t1[t1_start]; |
e = (BoundEntry *)((char *)page + t2_start); |
addr = start - e->start; |
if (addr > e->size) |
e = __bound_find_region(e, p); |
/* test if invalid region */ |
if (e->size == EMPTY_SIZE || (size_t)p != e->start) |
return -1; |
/* compute the size we put in invalid regions */ |
if (e->is_invalid) |
empty_size = INVALID_SIZE; |
else |
empty_size = EMPTY_SIZE; |
size = e->size; |
end = start + size; |
/* now we can free each entry */ |
t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS); |
t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
delete_region(e, p, empty_size); |
if (t1_end == t1_start) { |
/* same ending page */ |
e2 = (BoundEntry *)((char *)page + t2_end); |
if (e2 > e) { |
e++; |
for(;e<e2;e++) { |
e->start = 0; |
e->size = empty_size; |
} |
delete_region(e, p, empty_size); |
} |
} else { |
/* mark until end of page */ |
e2 = page + BOUND_T2_SIZE; |
e++; |
for(;e<e2;e++) { |
e->start = 0; |
e->size = empty_size; |
} |
/* mark intermediate pages, if any */ |
/* XXX: should free them */ |
for(i=t1_start+1;i<t1_end;i++) { |
page = get_page(i); |
e2 = page + BOUND_T2_SIZE; |
for(e=page;e<e2;e++) { |
e->start = 0; |
e->size = empty_size; |
} |
} |
/* last page */ |
page = get_page(t1_end); |
e2 = (BoundEntry *)((char *)page + t2_end); |
for(e=page;e<e2;e++) { |
e->start = 0; |
e->size = empty_size; |
} |
delete_region(e, p, empty_size); |
} |
dprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__); |
return 0; |
} |
/* return the size of the region starting at p, or EMPTY_SIZE if non |
existent region. */ |
static size_t get_region_size(void *p) |
{ |
size_t addr = (size_t)p; |
BoundEntry *e; |
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; |
e = (BoundEntry *)((char *)e + |
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); |
addr -= e->start; |
if (addr > e->size) |
e = __bound_find_region(e, p); |
if (e->start != (size_t)p) |
return EMPTY_SIZE; |
return e->size; |
} |
/* patched memory functions */ |
/* force compiler to perform stores coded up to this point */ |
#define barrier() __asm__ __volatile__ ("": : : "memory") |
static void install_malloc_hooks(void) |
{ |
#ifdef CONFIG_TCC_MALLOC_HOOKS |
saved_malloc_hook = __malloc_hook; |
saved_free_hook = __free_hook; |
saved_realloc_hook = __realloc_hook; |
saved_memalign_hook = __memalign_hook; |
__malloc_hook = __bound_malloc; |
__free_hook = __bound_free; |
__realloc_hook = __bound_realloc; |
__memalign_hook = __bound_memalign; |
barrier(); |
#endif |
} |
static void restore_malloc_hooks(void) |
{ |
#ifdef CONFIG_TCC_MALLOC_HOOKS |
__malloc_hook = saved_malloc_hook; |
__free_hook = saved_free_hook; |
__realloc_hook = saved_realloc_hook; |
__memalign_hook = saved_memalign_hook; |
barrier(); |
#endif |
} |
static void *libc_malloc(size_t size) |
{ |
void *ptr; |
restore_malloc_hooks(); |
ptr = malloc(size); |
install_malloc_hooks(); |
return ptr; |
} |
static void libc_free(void *ptr) |
{ |
restore_malloc_hooks(); |
free(ptr); |
install_malloc_hooks(); |
} |
/* XXX: we should use a malloc which ensure that it is unlikely that |
two malloc'ed data have the same address if 'free' are made in |
between. */ |
void *__bound_malloc(size_t size, const void *caller) |
{ |
void *ptr; |
/* we allocate one more byte to ensure the regions will be |
separated by at least one byte. With the glibc malloc, it may |
be in fact not necessary */ |
ptr = libc_malloc(size + 1); |
if (!ptr) |
return NULL; |
dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", |
__FILE__, __FUNCTION__, ptr, size); |
__bound_new_region(ptr, size); |
return ptr; |
} |
void *__bound_memalign(size_t size, size_t align, const void *caller) |
{ |
void *ptr; |
restore_malloc_hooks(); |
#ifndef HAVE_MEMALIGN |
if (align > 4) { |
/* XXX: handle it ? */ |
ptr = NULL; |
} else { |
/* we suppose that malloc aligns to at least four bytes */ |
ptr = malloc(size + 1); |
} |
#else |
/* we allocate one more byte to ensure the regions will be |
separated by at least one byte. With the glibc malloc, it may |
be in fact not necessary */ |
ptr = memalign(size + 1, align); |
#endif |
install_malloc_hooks(); |
if (!ptr) |
return NULL; |
dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", |
__FILE__, __FUNCTION__, ptr, size); |
__bound_new_region(ptr, size); |
return ptr; |
} |
void __bound_free(void *ptr, const void *caller) |
{ |
if (ptr == NULL) |
return; |
if (__bound_delete_region(ptr) != 0) |
bound_error("freeing invalid region"); |
libc_free(ptr); |
} |
void *__bound_realloc(void *ptr, size_t size, const void *caller) |
{ |
void *ptr1; |
size_t old_size; |
if (size == 0) { |
__bound_free(ptr, caller); |
return NULL; |
} else { |
ptr1 = __bound_malloc(size, caller); |
if (ptr == NULL || ptr1 == NULL) |
return ptr1; |
old_size = get_region_size(ptr); |
if (old_size == EMPTY_SIZE) |
bound_error("realloc'ing invalid pointer"); |
memcpy(ptr1, ptr, old_size); |
__bound_free(ptr, caller); |
return ptr1; |
} |
} |
#ifndef CONFIG_TCC_MALLOC_HOOKS |
void *__bound_calloc(size_t nmemb, size_t size) |
{ |
void *ptr; |
size = size * nmemb; |
ptr = __bound_malloc(size, NULL); |
if (!ptr) |
return NULL; |
memset(ptr, 0, size); |
return ptr; |
} |
#endif |
#if 0 |
static void bound_dump(void) |
{ |
BoundEntry *page, *e; |
size_t i, j; |
fprintf(stderr, "region dump:\n"); |
for(i=0;i<BOUND_T1_SIZE;i++) { |
page = __bound_t1[i]; |
for(j=0;j<BOUND_T2_SIZE;j++) { |
e = page + j; |
/* do not print invalid or empty entries */ |
if (e->size != EMPTY_SIZE && e->start != 0) { |
fprintf(stderr, "%08x:", |
(i << (BOUND_T2_BITS + BOUND_T3_BITS)) + |
(j << BOUND_T3_BITS)); |
do { |
fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size); |
e = e->next; |
} while (e != NULL); |
fprintf(stderr, "\n"); |
} |
} |
} |
} |
#endif |
/* some useful checked functions */ |
/* check that (p ... p + size - 1) lies inside 'p' region, if any */ |
static void __bound_check(const void *p, size_t size) |
{ |
if (size == 0) |
return; |
p = __bound_ptr_add((void *)p, size - 1); |
if (p == INVALID_POINTER) |
bound_error("invalid pointer"); |
} |
void *__bound_memcpy(void *dst, const void *src, size_t size) |
{ |
void* p; |
dprintf(stderr, "%s %s: start, dst=%p src=%p size=%p\n", __FILE__, __FUNCTION__, dst, src, size); |
__bound_check(dst, size); |
__bound_check(src, size); |
/* check also region overlap */ |
if (src >= dst && src < dst + size) |
bound_error("overlapping regions in memcpy()"); |
p = memcpy(dst, src, size); |
dprintf(stderr, "%s %s: end, p=%p\n", __FILE__, __FUNCTION__, p); |
return p; |
} |
void *__bound_memmove(void *dst, const void *src, size_t size) |
{ |
__bound_check(dst, size); |
__bound_check(src, size); |
return memmove(dst, src, size); |
} |
void *__bound_memset(void *dst, int c, size_t size) |
{ |
__bound_check(dst, size); |
return memset(dst, c, size); |
} |
/* XXX: could be optimized */ |
int __bound_strlen(const char *s) |
{ |
const char *p; |
size_t len; |
len = 0; |
for(;;) { |
p = __bound_ptr_indir1((char *)s, len); |
if (p == INVALID_POINTER) |
bound_error("bad pointer in strlen()"); |
if (*p == '\0') |
break; |
len++; |
} |
return len; |
} |
char *__bound_strcpy(char *dst, const char *src) |
{ |
size_t len; |
void *p; |
dprintf(stderr, "%s %s: strcpy start, dst=%p src=%p\n", __FILE__, __FUNCTION__, dst, src); |
len = __bound_strlen(src); |
p = __bound_memcpy(dst, src, len + 1); |
dprintf(stderr, "%s %s: strcpy end, p=%p\n", __FILE__, __FUNCTION__, dst, src, p); |
return p; |
} |
/programs/develop/ktcc/trunk/source/lib/buildtcclib1.bat |
---|
0,0 → 1,2 |
:kos32-gcc -c libtcc1.c -DTCC_TARGET_I386 -ID:\VSProjects\msys-kos32-4.8.2\sdk\sources\newlib\libc\include |
D:\VSProjects\msys-kos32-4.8.2\ktcc\trunk\libc\kos32-tcc.exe libtcc1.c -c -DTCC_TARGET_I386 |
/programs/develop/ktcc/trunk/source/lib/lib-arm64.c |
---|
0,0 → 1,652 |
/* |
* TCC runtime library for arm64. |
* |
* Copyright (c) 2015 Edmund Grimley Evans |
* |
* Copying and distribution of this file, with or without modification, |
* are permitted in any medium without royalty provided the copyright |
* notice and this notice are preserved. This file is offered as-is, |
* without any warranty. |
*/ |
#include <stdint.h> |
#include <string.h> |
void __clear_cache(void *beg, void *end) |
{ |
__arm64_clear_cache(beg, end); |
} |
typedef struct { |
uint64_t x0, x1; |
} u128_t; |
static long double f3_zero(int sgn) |
{ |
long double f; |
u128_t x = { 0, (uint64_t)sgn << 63 }; |
memcpy(&f, &x, 16); |
return f; |
} |
static long double f3_infinity(int sgn) |
{ |
long double f; |
u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 }; |
memcpy(&f, &x, 16); |
return f; |
} |
static long double f3_NaN(void) |
{ |
long double f; |
#if 0 |
// ARM's default NaN usually has just the top fraction bit set: |
u128_t x = { 0, 0x7fff800000000000 }; |
#else |
// GCC's library sets all fraction bits: |
u128_t x = { -1, 0x7fffffffffffffff }; |
#endif |
memcpy(&f, &x, 16); |
return f; |
} |
static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt) |
{ |
u128_t x = { mnt.x0, |
mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 }; |
memcpy(f, &x, 16); |
return 1; |
} |
static int fp3_detect_NaNs(long double *f, |
int a_sgn, int a_exp, u128_t a, |
int b_sgn, int b_exp, u128_t b) |
{ |
// Detect signalling NaNs: |
if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1)) |
return fp3_convert_NaN(f, a_sgn, a); |
if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1)) |
return fp3_convert_NaN(f, b_sgn, b); |
// Detect quiet NaNs: |
if (a_exp == 32767 && (a.x0 | a.x1 << 16)) |
return fp3_convert_NaN(f, a_sgn, a); |
if (b_exp == 32767 && (b.x0 | b.x1 << 16)) |
return fp3_convert_NaN(f, b_sgn, b); |
return 0; |
} |
static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f) |
{ |
u128_t x; |
memcpy(&x, &f, 16); |
*sgn = x.x1 >> 63; |
*exp = x.x1 >> 48 & 32767; |
x.x1 = x.x1 << 16 >> 16; |
if (*exp) |
x.x1 |= (uint64_t)1 << 48; |
else |
*exp = 1; |
*mnt = x; |
} |
static u128_t f3_normalise(int32_t *exp, u128_t mnt) |
{ |
int sh; |
if (!(mnt.x0 | mnt.x1)) |
return mnt; |
if (!mnt.x1) { |
mnt.x1 = mnt.x0; |
mnt.x0 = 0; |
*exp -= 64; |
} |
for (sh = 32; sh; sh >>= 1) { |
if (!(mnt.x1 >> (64 - sh))) { |
mnt.x1 = mnt.x1 << sh | mnt.x0 >> (64 - sh); |
mnt.x0 = mnt.x0 << sh; |
*exp -= sh; |
} |
} |
return mnt; |
} |
static u128_t f3_sticky_shift(int32_t sh, u128_t x) |
{ |
if (sh >= 128) { |
x.x0 = !!(x.x0 | x.x1); |
x.x1 = 0; |
return x; |
} |
if (sh >= 64) { |
x.x0 = x.x1 | !!x.x0; |
x.x1 = 0; |
sh -= 64; |
} |
if (sh > 0) { |
x.x0 = x.x0 >> sh | x.x1 << (64 - sh) | !!(x.x0 << (64 - sh)); |
x.x1 = x.x1 >> sh; |
} |
return x; |
} |
static long double f3_round(int sgn, int32_t exp, u128_t x) |
{ |
long double f; |
int error; |
if (exp > 0) { |
x = f3_sticky_shift(13, x); |
} |
else { |
x = f3_sticky_shift(14 - exp, x); |
exp = 0; |
} |
error = x.x0 & 3; |
x.x0 = x.x0 >> 2 | x.x1 << 62; |
x.x1 = x.x1 >> 2; |
if (error == 3 || ((error == 2) & (x.x0 & 1))) { |
if (!++x.x0) { |
++x.x1; |
if (x.x1 == (uint64_t)1 << 48) |
exp = 1; |
else if (x.x1 == (uint64_t)1 << 49) { |
++exp; |
x.x0 = x.x0 >> 1 | x.x1 << 63; |
x.x1 = x.x1 >> 1; |
} |
} |
} |
if (exp >= 32767) |
return f3_infinity(sgn); |
x.x1 = x.x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63; |
memcpy(&f, &x, 16); |
return f; |
} |
static long double f3_add(long double fa, long double fb, int neg) |
{ |
u128_t a, b, x; |
int32_t a_exp, b_exp, x_exp; |
int a_sgn, b_sgn, x_sgn; |
long double fx; |
f3_unpack(&a_sgn, &a_exp, &a, fa); |
f3_unpack(&b_sgn, &b_exp, &b, fb); |
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b)) |
return fx; |
b_sgn ^= neg; |
// Handle infinities and zeroes: |
if (a_exp == 32767 && b_exp == 32767 && a_sgn != b_sgn) |
return f3_NaN(); |
if (a_exp == 32767) |
return f3_infinity(a_sgn); |
if (b_exp == 32767) |
return f3_infinity(b_sgn); |
if (!(a.x0 | a.x1 | b.x0 | b.x1)) |
return f3_zero(a_sgn & b_sgn); |
a.x1 = a.x1 << 3 | a.x0 >> 61; |
a.x0 = a.x0 << 3; |
b.x1 = b.x1 << 3 | b.x0 >> 61; |
b.x0 = b.x0 << 3; |
if (a_exp <= b_exp) { |
a = f3_sticky_shift(b_exp - a_exp, a); |
a_exp = b_exp; |
} |
else { |
b = f3_sticky_shift(a_exp - b_exp, b); |
b_exp = a_exp; |
} |
x_sgn = a_sgn; |
x_exp = a_exp; |
if (a_sgn == b_sgn) { |
x.x0 = a.x0 + b.x0; |
x.x1 = a.x1 + b.x1 + (x.x0 < a.x0); |
} |
else { |
x.x0 = a.x0 - b.x0; |
x.x1 = a.x1 - b.x1 - (x.x0 > a.x0); |
if (x.x1 >> 63) { |
x_sgn ^= 1; |
x.x0 = -x.x0; |
x.x1 = -x.x1 - !!x.x0; |
} |
} |
if (!(x.x0 | x.x1)) |
return f3_zero(0); |
x = f3_normalise(&x_exp, x); |
return f3_round(x_sgn, x_exp + 12, x); |
} |
long double __addtf3(long double a, long double b) |
{ |
return f3_add(a, b, 0); |
} |
long double __subtf3(long double a, long double b) |
{ |
return f3_add(a, b, 1); |
} |
long double __multf3(long double fa, long double fb) |
{ |
u128_t a, b, x; |
int32_t a_exp, b_exp, x_exp; |
int a_sgn, b_sgn, x_sgn; |
long double fx; |
f3_unpack(&a_sgn, &a_exp, &a, fa); |
f3_unpack(&b_sgn, &b_exp, &b, fb); |
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b)) |
return fx; |
// Handle infinities and zeroes: |
if ((a_exp == 32767 && !(b.x0 | b.x1)) || |
(b_exp == 32767 && !(a.x0 | a.x1))) |
return f3_NaN(); |
if (a_exp == 32767 || b_exp == 32767) |
return f3_infinity(a_sgn ^ b_sgn); |
if (!(a.x0 | a.x1) || !(b.x0 | b.x1)) |
return f3_zero(a_sgn ^ b_sgn); |
a = f3_normalise(&a_exp, a); |
b = f3_normalise(&b_exp, b); |
x_sgn = a_sgn ^ b_sgn; |
x_exp = a_exp + b_exp - 16352; |
{ |
// Convert to base (1 << 30), discarding bottom 6 bits, which are zero, |
// so there are (32, 30, 30, 30) bits in (a3, a2, a1, a0): |
uint64_t a0 = a.x0 << 28 >> 34; |
uint64_t b0 = b.x0 << 28 >> 34; |
uint64_t a1 = a.x0 >> 36 | a.x1 << 62 >> 34; |
uint64_t b1 = b.x0 >> 36 | b.x1 << 62 >> 34; |
uint64_t a2 = a.x1 << 32 >> 34; |
uint64_t b2 = b.x1 << 32 >> 34; |
uint64_t a3 = a.x1 >> 32; |
uint64_t b3 = b.x1 >> 32; |
// Use 16 small multiplications and additions that do not overflow: |
uint64_t x0 = a0 * b0; |
uint64_t x1 = (x0 >> 30) + a0 * b1 + a1 * b0; |
uint64_t x2 = (x1 >> 30) + a0 * b2 + a1 * b1 + a2 * b0; |
uint64_t x3 = (x2 >> 30) + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; |
uint64_t x4 = (x3 >> 30) + a1 * b3 + a2 * b2 + a3 * b1; |
uint64_t x5 = (x4 >> 30) + a2 * b3 + a3 * b2; |
uint64_t x6 = (x5 >> 30) + a3 * b3; |
// We now have (64, 30, 30, ...) bits in (x6, x5, x4, ...). |
// Take the top 128 bits, setting bottom bit if any lower bits were set: |
uint64_t y0 = (x5 << 34 | x4 << 34 >> 30 | x3 << 34 >> 60 | |
!!(x3 << 38 | (x2 | x1 | x0) << 34)); |
uint64_t y1 = x6; |
// Top bit may be zero. Renormalise: |
if (!(y1 >> 63)) { |
y1 = y1 << 1 | y0 >> 63; |
y0 = y0 << 1; |
--x_exp; |
} |
x.x0 = y0; |
x.x1 = y1; |
} |
return f3_round(x_sgn, x_exp, x); |
} |
long double __divtf3(long double fa, long double fb) |
{ |
u128_t a, b, x; |
int32_t a_exp, b_exp, x_exp; |
int a_sgn, b_sgn, x_sgn, i; |
long double fx; |
f3_unpack(&a_sgn, &a_exp, &a, fa); |
f3_unpack(&b_sgn, &b_exp, &b, fb); |
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b)) |
return fx; |
// Handle infinities and zeroes: |
if ((a_exp == 32767 && b_exp == 32767) || |
(!(a.x0 | a.x1) && !(b.x0 | b.x1))) |
return f3_NaN(); |
if (a_exp == 32767 || !(b.x0 | b.x1)) |
return f3_infinity(a_sgn ^ b_sgn); |
if (!(a.x0 | a.x1) || b_exp == 32767) |
return f3_zero(a_sgn ^ b_sgn); |
a = f3_normalise(&a_exp, a); |
b = f3_normalise(&b_exp, b); |
x_sgn = a_sgn ^ b_sgn; |
x_exp = a_exp - b_exp + 16395; |
a.x0 = a.x0 >> 1 | a.x1 << 63; |
a.x1 = a.x1 >> 1; |
b.x0 = b.x0 >> 1 | b.x1 << 63; |
b.x1 = b.x1 >> 1; |
x.x0 = 0; |
x.x1 = 0; |
for (i = 0; i < 116; i++) { |
x.x1 = x.x1 << 1 | x.x0 >> 63; |
x.x0 = x.x0 << 1; |
if (a.x1 > b.x1 || (a.x1 == b.x1 && a.x0 >= b.x0)) { |
a.x1 = a.x1 - b.x1 - (a.x0 < b.x0); |
a.x0 = a.x0 - b.x0; |
x.x0 |= 1; |
} |
a.x1 = a.x1 << 1 | a.x0 >> 63; |
a.x0 = a.x0 << 1; |
} |
x.x0 |= !!(a.x0 | a.x1); |
x = f3_normalise(&x_exp, x); |
return f3_round(x_sgn, x_exp, x); |
} |
long double __extendsftf2(float f) |
{ |
long double fx; |
u128_t x; |
uint32_t a; |
uint64_t aa; |
memcpy(&a, &f, 4); |
aa = a; |
x.x0 = 0; |
if (!(a << 1)) |
x.x1 = aa << 32; |
else if (a << 1 >> 24 == 255) |
x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 | |
(uint64_t)!!(a << 9) << 47); |
else |
x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 | |
aa << 41 >> 16); |
memcpy(&fx, &x, 16); |
return fx; |
} |
long double __extenddftf2(double f) |
{ |
long double fx; |
u128_t x; |
uint64_t a; |
memcpy(&a, &f, 8); |
x.x0 = a << 60; |
if (!(a << 1)) |
x.x1 = a; |
else if (a << 1 >> 53 == 2047) |
x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 | |
(uint64_t)!!(a << 12) << 47); |
else |
x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16; |
memcpy(&fx, &x, 16); |
return fx; |
} |
float __trunctfsf2(long double f) |
{ |
u128_t mnt; |
int32_t exp; |
int sgn; |
uint32_t x; |
float fx; |
f3_unpack(&sgn, &exp, &mnt, f); |
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16)) |
x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff); |
else if (exp > 16510) |
x = 0x7f800000 | (uint32_t)sgn << 31; |
else if (exp < 16233) |
x = (uint32_t)sgn << 31; |
else { |
exp -= 16257; |
x = mnt.x1 >> 23 | !!(mnt.x0 | mnt.x1 << 41); |
if (exp < 0) { |
x = x >> -exp | !!(x << (32 + exp)); |
exp = 0; |
} |
if ((x & 3) == 3 || (x & 7) == 6) |
x += 4; |
x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31; |
} |
memcpy(&fx, &x, 4); |
return fx; |
} |
double __trunctfdf2(long double f) |
{ |
u128_t mnt; |
int32_t exp; |
int sgn; |
uint64_t x; |
double fx; |
f3_unpack(&sgn, &exp, &mnt, f); |
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16)) |
x = (0x7ff8000000000000 | (uint64_t)sgn << 63 | |
mnt.x1 << 16 >> 12 | mnt.x0 >> 60); |
else if (exp > 17406) |
x = 0x7ff0000000000000 | (uint64_t)sgn << 63; |
else if (exp < 15308) |
x = (uint64_t)sgn << 63; |
else { |
exp -= 15361; |
x = mnt.x1 << 6 | mnt.x0 >> 58 | !!(mnt.x0 << 6); |
if (exp < 0) { |
x = x >> -exp | !!(x << (64 + exp)); |
exp = 0; |
} |
if ((x & 3) == 3 || (x & 7) == 6) |
x += 4; |
x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63; |
} |
memcpy(&fx, &x, 8); |
return fx; |
} |
int32_t __fixtfsi(long double fa) |
{ |
u128_t a; |
int32_t a_exp; |
int a_sgn; |
int32_t x; |
f3_unpack(&a_sgn, &a_exp, &a, fa); |
if (a_exp < 16369) |
return 0; |
if (a_exp > 16413) |
return a_sgn ? -0x80000000 : 0x7fffffff; |
x = a.x1 >> (16431 - a_exp); |
return a_sgn ? -x : x; |
} |
int64_t __fixtfdi(long double fa) |
{ |
u128_t a; |
int32_t a_exp; |
int a_sgn; |
int64_t x; |
f3_unpack(&a_sgn, &a_exp, &a, fa); |
if (a_exp < 16383) |
return 0; |
if (a_exp > 16445) |
return a_sgn ? -0x8000000000000000 : 0x7fffffffffffffff; |
x = (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp); |
return a_sgn ? -x : x; |
} |
uint32_t __fixunstfsi(long double fa) |
{ |
u128_t a; |
int32_t a_exp; |
int a_sgn; |
f3_unpack(&a_sgn, &a_exp, &a, fa); |
if (a_sgn || a_exp < 16369) |
return 0; |
if (a_exp > 16414) |
return -1; |
return a.x1 >> (16431 - a_exp); |
} |
uint64_t __fixunstfdi(long double fa) |
{ |
u128_t a; |
int32_t a_exp; |
int a_sgn; |
f3_unpack(&a_sgn, &a_exp, &a, fa); |
if (a_sgn || a_exp < 16383) |
return 0; |
if (a_exp > 16446) |
return -1; |
return (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp); |
} |
long double __floatsitf(int32_t a) |
{ |
int sgn = 0; |
int exp = 16414; |
uint32_t mnt = a; |
u128_t x = { 0, 0 }; |
long double f; |
int i; |
if (a) { |
if (a < 0) { |
sgn = 1; |
mnt = -mnt; |
} |
for (i = 16; i; i >>= 1) |
if (!(mnt >> (32 - i))) { |
mnt <<= i; |
exp -= i; |
} |
x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 | |
(uint64_t)(mnt << 1) << 16); |
} |
memcpy(&f, &x, 16); |
return f; |
} |
long double __floatditf(int64_t a) |
{ |
int sgn = 0; |
int exp = 16446; |
uint64_t mnt = a; |
u128_t x = { 0, 0 }; |
long double f; |
int i; |
if (a) { |
if (a < 0) { |
sgn = 1; |
mnt = -mnt; |
} |
for (i = 32; i; i >>= 1) |
if (!(mnt >> (64 - i))) { |
mnt <<= i; |
exp -= i; |
} |
x.x0 = mnt << 49; |
x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16; |
} |
memcpy(&f, &x, 16); |
return f; |
} |
long double __floatunsitf(uint32_t a) |
{ |
int exp = 16414; |
uint32_t mnt = a; |
u128_t x = { 0, 0 }; |
long double f; |
int i; |
if (a) { |
for (i = 16; i; i >>= 1) |
if (!(mnt >> (32 - i))) { |
mnt <<= i; |
exp -= i; |
} |
x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16; |
} |
memcpy(&f, &x, 16); |
return f; |
} |
long double __floatunditf(uint64_t a) |
{ |
int exp = 16446; |
uint64_t mnt = a; |
u128_t x = { 0, 0 }; |
long double f; |
int i; |
if (a) { |
for (i = 32; i; i >>= 1) |
if (!(mnt >> (64 - i))) { |
mnt <<= i; |
exp -= i; |
} |
x.x0 = mnt << 49; |
x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16; |
} |
memcpy(&f, &x, 16); |
return f; |
} |
static int f3_cmp(long double fa, long double fb) |
{ |
u128_t a, b; |
memcpy(&a, &fa, 16); |
memcpy(&b, &fb, 16); |
return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 : |
((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) || |
(b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 : |
a.x1 >> 63 != b.x1 >> 63 ? (int)(b.x1 >> 63) - (int)(a.x1 >> 63) : |
a.x1 < b.x1 ? (int)(a.x1 >> 63 << 1) - 1 : |
a.x1 > b.x1 ? 1 - (int)(a.x1 >> 63 << 1) : |
a.x0 < b.x0 ? (int)(a.x1 >> 63 << 1) - 1 : |
b.x0 < a.x0 ? 1 - (int)(a.x1 >> 63 << 1) : 0); |
} |
int __eqtf2(long double a, long double b) |
{ |
return !!f3_cmp(a, b); |
} |
int __netf2(long double a, long double b) |
{ |
return !!f3_cmp(a, b); |
} |
int __lttf2(long double a, long double b) |
{ |
return f3_cmp(a, b); |
} |
int __letf2(long double a, long double b) |
{ |
return f3_cmp(a, b); |
} |
int __gttf2(long double a, long double b) |
{ |
return -f3_cmp(b, a); |
} |
int __getf2(long double a, long double b) |
{ |
return -f3_cmp(b, a); |
} |
/programs/develop/ktcc/trunk/source/lib/libtcc1.c |
---|
0,0 → 1,753 |
/* TCC runtime library. |
Parts of this code are (c) 2002 Fabrice Bellard |
Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc. |
This file is free software; you can redistribute it and/or modify it |
under the terms of the GNU General Public License as published by the |
Free Software Foundation; either version 2, or (at your option) any |
later version. |
In addition to the permissions in the GNU General Public License, the |
Free Software Foundation gives you unlimited permission to link the |
compiled version of this file into combinations with other programs, |
and to distribute those combinations without any restriction coming |
from the use of this file. (The General Public License restrictions |
do apply in other respects; for example, they cover modification of |
the file, and distribution when not linked into a combine |
executable.) |
This file is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; see the file COPYING. If not, write to |
the Free Software Foundation, 59 Temple Place - Suite 330, |
Boston, MA 02111-1307, USA. |
*/ |
//#include <stdint.h> |
#define W_TYPE_SIZE 32 |
#define BITS_PER_UNIT 8 |
typedef int Wtype; |
typedef unsigned int UWtype; |
typedef unsigned int USItype; |
typedef long long DWtype; |
typedef unsigned long long UDWtype; |
struct DWstruct { |
Wtype low, high; |
}; |
typedef union |
{ |
struct DWstruct s; |
DWtype ll; |
} DWunion; |
typedef long double XFtype; |
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) |
/* the following deal with IEEE single-precision numbers */ |
#define EXCESS 126 |
#define SIGNBIT 0x80000000 |
#define HIDDEN (1 << 23) |
#define SIGN(fp) ((fp) & SIGNBIT) |
#define EXP(fp) (((fp) >> 23) & 0xFF) |
#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN) |
#define PACK(s,e,m) ((s) | ((e) << 23) | (m)) |
/* the following deal with IEEE double-precision numbers */ |
#define EXCESSD 1022 |
#define HIDDEND (1 << 20) |
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) |
#define SIGND(fp) ((fp.l.upper) & SIGNBIT) |
#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ |
(fp.l.lower >> 22)) |
#define HIDDEND_LL ((long long)1 << 52) |
#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL) |
#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m)) |
/* the following deal with x86 long double-precision numbers */ |
#define EXCESSLD 16382 |
#define EXPLD(fp) (fp.l.upper & 0x7fff) |
#define SIGNLD(fp) ((fp.l.upper) & 0x8000) |
/* only for x86 */ |
union ldouble_long { |
long double ld; |
struct { |
unsigned long long lower; |
unsigned short upper; |
} l; |
}; |
union double_long { |
double d; |
#if 1 |
struct { |
unsigned int lower; |
int upper; |
} l; |
#else |
struct { |
int upper; |
unsigned int lower; |
} l; |
#endif |
long long ll; |
}; |
union float_long { |
float f; |
unsigned int l; |
}; |
/* XXX: we don't support several builtin supports for now */ |
#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM) |
/* XXX: use gcc/tcc intrinsic ? */ |
#if defined(TCC_TARGET_I386) |
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ |
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \ |
: "=r" ((USItype) (sh)), \ |
"=&r" ((USItype) (sl)) \ |
: "0" ((USItype) (ah)), \ |
"g" ((USItype) (bh)), \ |
"1" ((USItype) (al)), \ |
"g" ((USItype) (bl))) |
#define umul_ppmm(w1, w0, u, v) \ |
__asm__ ("mull %3" \ |
: "=a" ((USItype) (w0)), \ |
"=d" ((USItype) (w1)) \ |
: "%0" ((USItype) (u)), \ |
"rm" ((USItype) (v))) |
#define udiv_qrnnd(q, r, n1, n0, dv) \ |
__asm__ ("divl %4" \ |
: "=a" ((USItype) (q)), \ |
"=d" ((USItype) (r)) \ |
: "0" ((USItype) (n0)), \ |
"1" ((USItype) (n1)), \ |
"rm" ((USItype) (dv))) |
#define count_leading_zeros(count, x) \ |
do { \ |
USItype __cbtmp; \ |
__asm__ ("bsrl %1,%0" \ |
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \ |
(count) = __cbtmp ^ 31; \ |
} while (0) |
#else |
#error unsupported CPU type |
#endif |
/* most of this code is taken from libgcc2.c from gcc */ |
static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) |
{ |
DWunion ww; |
DWunion nn, dd; |
DWunion rr; |
UWtype d0, d1, n0, n1, n2; |
UWtype q0, q1; |
UWtype b, bm; |
nn.ll = n; |
dd.ll = d; |
d0 = dd.s.low; |
d1 = dd.s.high; |
n0 = nn.s.low; |
n1 = nn.s.high; |
#if !defined(UDIV_NEEDS_NORMALIZATION) |
if (d1 == 0) |
{ |
if (d0 > n1) |
{ |
/* 0q = nn / 0D */ |
udiv_qrnnd (q0, n0, n1, n0, d0); |
q1 = 0; |
/* Remainder in n0. */ |
} |
else |
{ |
/* qq = NN / 0d */ |
if (d0 == 0) |
d0 = 1 / d0; /* Divide intentionally by zero. */ |
udiv_qrnnd (q1, n1, 0, n1, d0); |
udiv_qrnnd (q0, n0, n1, n0, d0); |
/* Remainder in n0. */ |
} |
if (rp != 0) |
{ |
rr.s.low = n0; |
rr.s.high = 0; |
*rp = rr.ll; |
} |
} |
#else /* UDIV_NEEDS_NORMALIZATION */ |
if (d1 == 0) |
{ |
if (d0 > n1) |
{ |
/* 0q = nn / 0D */ |
count_leading_zeros (bm, d0); |
if (bm != 0) |
{ |
/* Normalize, i.e. make the most significant bit of the |
denominator set. */ |
d0 = d0 << bm; |
n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); |
n0 = n0 << bm; |
} |
udiv_qrnnd (q0, n0, n1, n0, d0); |
q1 = 0; |
/* Remainder in n0 >> bm. */ |
} |
else |
{ |
/* qq = NN / 0d */ |
if (d0 == 0) |
d0 = 1 / d0; /* Divide intentionally by zero. */ |
count_leading_zeros (bm, d0); |
if (bm == 0) |
{ |
/* From (n1 >= d0) /\ (the most significant bit of d0 is set), |
conclude (the most significant bit of n1 is set) /\ (the |
leading quotient digit q1 = 1). |
This special case is necessary, not an optimization. |
(Shifts counts of W_TYPE_SIZE are undefined.) */ |
n1 -= d0; |
q1 = 1; |
} |
else |
{ |
/* Normalize. */ |
b = W_TYPE_SIZE - bm; |
d0 = d0 << bm; |
n2 = n1 >> b; |
n1 = (n1 << bm) | (n0 >> b); |
n0 = n0 << bm; |
udiv_qrnnd (q1, n1, n2, n1, d0); |
} |
/* n1 != d0... */ |
udiv_qrnnd (q0, n0, n1, n0, d0); |
/* Remainder in n0 >> bm. */ |
} |
if (rp != 0) |
{ |
rr.s.low = n0 >> bm; |
rr.s.high = 0; |
*rp = rr.ll; |
} |
} |
#endif /* UDIV_NEEDS_NORMALIZATION */ |
else |
{ |
if (d1 > n1) |
{ |
/* 00 = nn / DD */ |
q0 = 0; |
q1 = 0; |
/* Remainder in n1n0. */ |
if (rp != 0) |
{ |
rr.s.low = n0; |
rr.s.high = n1; |
*rp = rr.ll; |
} |
} |
else |
{ |
/* 0q = NN / dd */ |
count_leading_zeros (bm, d1); |
if (bm == 0) |
{ |
/* From (n1 >= d1) /\ (the most significant bit of d1 is set), |
conclude (the most significant bit of n1 is set) /\ (the |
quotient digit q0 = 0 or 1). |
This special case is necessary, not an optimization. */ |
/* The condition on the next line takes advantage of that |
n1 >= d1 (true due to program flow). */ |
if (n1 > d1 || n0 >= d0) |
{ |
q0 = 1; |
sub_ddmmss (n1, n0, n1, n0, d1, d0); |
} |
else |
q0 = 0; |
q1 = 0; |
if (rp != 0) |
{ |
rr.s.low = n0; |
rr.s.high = n1; |
*rp = rr.ll; |
} |
} |
else |
{ |
UWtype m1, m0; |
/* Normalize. */ |
b = W_TYPE_SIZE - bm; |
d1 = (d1 << bm) | (d0 >> b); |
d0 = d0 << bm; |
n2 = n1 >> b; |
n1 = (n1 << bm) | (n0 >> b); |
n0 = n0 << bm; |
udiv_qrnnd (q0, n1, n2, n1, d1); |
umul_ppmm (m1, m0, q0, d0); |
if (m1 > n1 || (m1 == n1 && m0 > n0)) |
{ |
q0--; |
sub_ddmmss (m1, m0, m1, m0, d1, d0); |
} |
q1 = 0; |
/* Remainder in (n1n0 - m1m0) >> bm. */ |
if (rp != 0) |
{ |
sub_ddmmss (n1, n0, n1, n0, m1, m0); |
rr.s.low = (n1 << b) | (n0 >> bm); |
rr.s.high = n1 >> bm; |
*rp = rr.ll; |
} |
} |
} |
} |
ww.s.low = q0; |
ww.s.high = q1; |
return ww.ll; |
} |
#define __negdi2(a) (-(a)) |
long long __divdi3(long long u, long long v) |
{ |
int c = 0; |
DWunion uu, vv; |
DWtype w; |
uu.ll = u; |
vv.ll = v; |
if (uu.s.high < 0) { |
c = ~c; |
uu.ll = __negdi2 (uu.ll); |
} |
if (vv.s.high < 0) { |
c = ~c; |
vv.ll = __negdi2 (vv.ll); |
} |
w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); |
if (c) |
w = __negdi2 (w); |
return w; |
} |
long long __moddi3(long long u, long long v) |
{ |
int c = 0; |
DWunion uu, vv; |
DWtype w; |
uu.ll = u; |
vv.ll = v; |
if (uu.s.high < 0) { |
c = ~c; |
uu.ll = __negdi2 (uu.ll); |
} |
if (vv.s.high < 0) |
vv.ll = __negdi2 (vv.ll); |
__udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w); |
if (c) |
w = __negdi2 (w); |
return w; |
} |
unsigned long long __udivdi3(unsigned long long u, unsigned long long v) |
{ |
return __udivmoddi4 (u, v, (UDWtype *) 0); |
} |
unsigned long long __umoddi3(unsigned long long u, unsigned long long v) |
{ |
UDWtype w; |
__udivmoddi4 (u, v, &w); |
return w; |
} |
/* XXX: fix tcc's code generator to do this instead */ |
long long __ashrdi3(long long a, int b) |
{ |
#ifdef __TINYC__ |
DWunion u; |
u.ll = a; |
if (b >= 32) { |
u.s.low = u.s.high >> (b - 32); |
u.s.high = u.s.high >> 31; |
} else if (b != 0) { |
u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b)); |
u.s.high = u.s.high >> b; |
} |
return u.ll; |
#else |
return a >> b; |
#endif |
} |
/* XXX: fix tcc's code generator to do this instead */ |
unsigned long long __lshrdi3(unsigned long long a, int b) |
{ |
#ifdef __TINYC__ |
DWunion u; |
u.ll = a; |
if (b >= 32) { |
u.s.low = (unsigned)u.s.high >> (b - 32); |
u.s.high = 0; |
} else if (b != 0) { |
u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b)); |
u.s.high = (unsigned)u.s.high >> b; |
} |
return u.ll; |
#else |
return a >> b; |
#endif |
} |
/* XXX: fix tcc's code generator to do this instead */ |
long long __ashldi3(long long a, int b) |
{ |
#ifdef __TINYC__ |
DWunion u; |
u.ll = a; |
if (b >= 32) { |
u.s.high = (unsigned)u.s.low << (b - 32); |
u.s.low = 0; |
} else if (b != 0) { |
u.s.high = ((unsigned)u.s.high << b) | ((unsigned)u.s.low >> (32 - b)); |
u.s.low = (unsigned)u.s.low << b; |
} |
return u.ll; |
#else |
return a << b; |
#endif |
} |
#ifndef COMMIT_4ad186c5ef61_IS_FIXED |
long long __tcc_cvt_ftol(long double x) |
{ |
unsigned c0, c1; |
long long ret; |
__asm__ __volatile__ ("fnstcw %0" : "=m" (c0)); |
c1 = c0 | 0x0C00; |
__asm__ __volatile__ ("fldcw %0" : : "m" (c1)); |
__asm__ __volatile__ ("fistpll %0" : "=m" (ret)); |
__asm__ __volatile__ ("fldcw %0" : : "m" (c0)); |
return ret; |
} |
#endif |
#endif /* !__x86_64__ */ |
/* XXX: fix tcc's code generator to do this instead */ |
float __floatundisf(unsigned long long a) |
{ |
DWunion uu; |
XFtype r; |
uu.ll = a; |
if (uu.s.high >= 0) { |
return (float)uu.ll; |
} else { |
r = (XFtype)uu.ll; |
r += 18446744073709551616.0; |
return (float)r; |
} |
} |
double __floatundidf(unsigned long long a) |
{ |
DWunion uu; |
XFtype r; |
uu.ll = a; |
if (uu.s.high >= 0) { |
return (double)uu.ll; |
} else { |
r = (XFtype)uu.ll; |
r += 18446744073709551616.0; |
return (double)r; |
} |
} |
long double __floatundixf(unsigned long long a) |
{ |
DWunion uu; |
XFtype r; |
uu.ll = a; |
if (uu.s.high >= 0) { |
return (long double)uu.ll; |
} else { |
r = (XFtype)uu.ll; |
r += 18446744073709551616.0; |
return (long double)r; |
} |
} |
unsigned long long __fixunssfdi (float a1) |
{ |
register union float_long fl1; |
register int exp; |
register unsigned long l; |
fl1.f = a1; |
if (fl1.l == 0) |
return (0); |
exp = EXP (fl1.l) - EXCESS - 24; |
l = MANT(fl1.l); |
if (exp >= 41) |
return (unsigned long long)-1; |
else if (exp >= 0) |
return (unsigned long long)l << exp; |
else if (exp >= -23) |
return l >> -exp; |
else |
return 0; |
} |
unsigned long long __fixunsdfdi (double a1) |
{ |
register union double_long dl1; |
register int exp; |
register unsigned long long l; |
dl1.d = a1; |
if (dl1.ll == 0) |
return (0); |
exp = EXPD (dl1) - EXCESSD - 53; |
l = MANTD_LL(dl1); |
if (exp >= 12) |
return (unsigned long long)-1; |
else if (exp >= 0) |
return l << exp; |
else if (exp >= -52) |
return l >> -exp; |
else |
return 0; |
} |
unsigned long long __fixunsxfdi (long double a1) |
{ |
register union ldouble_long dl1; |
register int exp; |
register unsigned long long l; |
dl1.ld = a1; |
if (dl1.l.lower == 0 && dl1.l.upper == 0) |
return (0); |
exp = EXPLD (dl1) - EXCESSLD - 64; |
l = dl1.l.lower; |
if (exp > 0) |
return (unsigned long long)-1; |
else if (exp >= -63) |
return l >> -exp; |
else |
return 0; |
} |
long long __fixsfdi (float a1) |
{ |
long long ret; int s; |
ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); |
return s ? ret : -ret; |
} |
long long __fixdfdi (double a1) |
{ |
long long ret; int s; |
ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); |
return s ? ret : -ret; |
} |
long long __fixxfdi (long double a1) |
{ |
long long ret; int s; |
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); |
return s ? ret : -ret; |
} |
#if defined(TCC_TARGET_X86_64) && !defined(_WIN64) |
#ifndef __TINYC__ |
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#else |
/* Avoid including stdlib.h because it is not easily available when |
cross compiling */ |
#include <stddef.h> /* size_t definition is needed for a x86_64-tcc to parse memset() */ |
extern void *malloc(unsigned long long); |
extern void *memset(void *s, int c, size_t n); |
extern void free(void*); |
extern void abort(void); |
#endif |
enum __va_arg_type { |
__va_gen_reg, __va_float_reg, __va_stack |
}; |
//This should be in sync with the declaration on our include/stdarg.h |
/* GCC compatible definition of va_list. */ |
typedef struct { |
unsigned int gp_offset; |
unsigned int fp_offset; |
union { |
unsigned int overflow_offset; |
char *overflow_arg_area; |
}; |
char *reg_save_area; |
} __va_list_struct; |
#undef __va_start |
#undef __va_arg |
#undef __va_copy |
#undef __va_end |
void __va_start(__va_list_struct *ap, void *fp) |
{ |
memset(ap, 0, sizeof(__va_list_struct)); |
*ap = *(__va_list_struct *)((char *)fp - 16); |
ap->overflow_arg_area = (char *)fp + ap->overflow_offset; |
ap->reg_save_area = (char *)fp - 176 - 16; |
} |
void *__va_arg(__va_list_struct *ap, |
enum __va_arg_type arg_type, |
int size, int align) |
{ |
size = (size + 7) & ~7; |
align = (align + 7) & ~7; |
switch (arg_type) { |
case __va_gen_reg: |
if (ap->gp_offset + size <= 48) { |
ap->gp_offset += size; |
return ap->reg_save_area + ap->gp_offset - size; |
} |
goto use_overflow_area; |
case __va_float_reg: |
if (ap->fp_offset < 128 + 48) { |
ap->fp_offset += 16; |
return ap->reg_save_area + ap->fp_offset - 16; |
} |
size = 8; |
goto use_overflow_area; |
case __va_stack: |
use_overflow_area: |
ap->overflow_arg_area += size; |
ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align); |
return ap->overflow_arg_area - size; |
default: |
#ifndef __TINYC__ |
fprintf(stderr, "unknown ABI type for __va_arg\n"); |
#endif |
abort(); |
} |
} |
#endif /* __x86_64__ */ |
/* Flushing for tccrun */ |
#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386) |
void __clear_cache(void *beginning, void *end) |
{ |
} |
#elif defined(TCC_TARGET_ARM) |
#define _GNU_SOURCE |
#include <unistd.h> |
#include <sys/syscall.h> |
#include <stdio.h> |
void __clear_cache(void *beginning, void *end) |
{ |
/* __ARM_NR_cacheflush is kernel private and should not be used in user space. |
* However, there is no ARM asm parser in tcc so we use it for now */ |
#if 1 |
syscall(__ARM_NR_cacheflush, beginning, end, 0); |
#else |
__asm__ ("push {r7}\n\t" |
"mov r7, #0xf0002\n\t" |
"mov r2, #0\n\t" |
"swi 0\n\t" |
"pop {r7}\n\t" |
"ret"); |
#endif |
} |
#else |
#warning __clear_cache not defined for this architecture, avoid using tcc -run |
#endif |
/programs/develop/ktcc/trunk/source/lib/testfp.c |
---|
0,0 → 1,510 |
/* |
* Test 128-bit floating-point arithmetic on arm64: |
* build with two different compilers and compare the output. |
* |
* Copyright (c) 2015 Edmund Grimley Evans |
* |
* Copying and distribution of this file, with or without modification, |
* are permitted in any medium without royalty provided the copyright |
* notice and this notice are preserved. This file is offered as-is, |
* without any warranty. |
*/ |
#include <stdint.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#define check(x) ((x) ? (void)0 : check_fail(#x, __FILE__, __LINE__)) |
void check_fail(const char *assertion, const char *file, unsigned int line) |
{ |
printf("%s:%d: Check (%s) failed.", file, line, assertion); |
exit(1); |
} |
typedef struct { |
unsigned long long x0, x1; |
} u128_t; |
float copy_fi(uint32_t x) |
{ |
float f; |
memcpy(&f, &x, 4); |
return f; |
} |
double copy_di(uint64_t x) |
{ |
double f; |
memcpy(&f, &x, 8); |
return f; |
} |
long double copy_ldi(u128_t x) |
{ |
long double f; |
memcpy(&f, &x, 16); |
return f; |
} |
uint32_t copy_if(float f) |
{ |
uint32_t x; |
memcpy(&x, &f, 4); |
return x; |
} |
uint64_t copy_id(double f) |
{ |
uint64_t x; |
memcpy(&x, &f, 8); |
return x; |
} |
u128_t copy_ild(long double f) |
{ |
u128_t x; |
memcpy(&x, &f, 16); |
return x; |
} |
long double make(int sgn, int exp, uint64_t high, uint64_t low) |
{ |
u128_t x = { low, |
(0x0000ffffffffffff & high) | |
(0x7fff000000000000 & (uint64_t)exp << 48) | |
(0x8000000000000000 & (uint64_t)sgn << 63) }; |
return copy_ldi(x); |
} |
void cmp(long double a, long double b) |
{ |
u128_t ax = copy_ild(a); |
u128_t bx = copy_ild(b); |
int eq = (a == b); |
int ne = (a != b); |
int lt = (a < b); |
int le = (a <= b); |
int gt = (a > b); |
int ge = (a >= b); |
check(eq == 0 || eq == 1); |
check(lt == 0 || lt == 1); |
check(gt == 0 || gt == 1); |
check(ne == !eq && le == (lt | eq) && ge == (gt | eq)); |
check(eq + lt + gt < 2); |
printf("cmp %016llx%016llx %016llx%016llx %d %d %d\n", |
ax.x1, ax.x0, bx.x1, bx.x0, lt, eq, gt); |
} |
void cmps(void) |
{ |
int i, j; |
for (i = 0; i < 2; i++) |
for (j = 0; j < 2; j++) |
cmp(make(i, 0, 0, 0), make(j, 0, 0, 0)); |
for (i = 0; i < 2; i++) { |
for (j = 0; j < 64; j++) { |
long double f1 = make(i, 32767, (uint64_t)1 << j, 0); |
long double f2 = make(i, 32767, 0, (uint64_t)1 << j); |
cmp(f1, 0); |
cmp(f2, 0); |
cmp(0, f1); |
cmp(0, f2); |
} |
} |
for (i = 0; i < 6; i++) |
for (j = 0; j < 6; j++) |
cmp(make(i & 1, i >> 1, 0, 0), |
make(j & 1, j >> 1, 0, 0)); |
for (i = 0; i < 2; i++) { |
for (j = 0; j < 2; j++) { |
int a, b; |
for (a = 0; a < 2; a++) { |
for (b = 0; b < 2; b++) { |
cmp(make(i, j, a, b), make(i, j, 0, 0)); |
cmp(make(i, j, 0, 0), make(i, j, a, b)); |
} |
} |
} |
} |
} |
void xop(const char *name, long double a, long double b, long double c) |
{ |
u128_t ax = copy_ild(a); |
u128_t bx = copy_ild(b); |
u128_t cx = copy_ild(c); |
printf("%s %016llx%016llx %016llx%016llx %016llx%016llx\n", |
name, ax.x1, ax.x0, bx.x1, bx.x0, cx.x1, cx.x0); |
} |
void fadd(long double a, long double b) |
{ |
xop("add", a, b, a + b); |
} |
void fsub(long double a, long double b) |
{ |
xop("sub", a, b, a - b); |
} |
void fmul(long double a, long double b) |
{ |
xop("mul", a, b, a * b); |
} |
void fdiv(long double a, long double b) |
{ |
xop("div", a, b, a / b); |
} |
void nanz(void) |
{ |
// Check NaNs: |
{ |
long double x[7]; |
int i, j, n = 0; |
x[n++] = make(0, 32000, 0x95132b76effc, 0xd79035214b4f8d53); |
x[n++] = make(1, 32001, 0xbe71d7a51587, 0x30601c6815d6c3ac); |
x[n++] = make(0, 32767, 0, 1); |
x[n++] = make(0, 32767, (uint64_t)1 << 46, 0); |
x[n++] = make(1, 32767, (uint64_t)1 << 47, 0); |
x[n++] = make(1, 32767, 0x7596c7099ad5, 0xe25fed2c58f73fc9); |
x[n++] = make(0, 32767, 0x835d143360f9, 0x5e315efb35630666); |
check(n == sizeof(x) / sizeof(*x)); |
for (i = 0; i < n; i++) { |
for (j = 0; j < n; j++) { |
fadd(x[i], x[j]); |
fsub(x[i], x[j]); |
fmul(x[i], x[j]); |
fdiv(x[i], x[j]); |
} |
} |
} |
// Check infinities and zeroes: |
{ |
long double x[6]; |
int i, j, n = 0; |
x[n++] = make(1, 32000, 0x62acda85f700, 0x47b6c9f35edc4044); |
x[n++] = make(0, 32001, 0x94b7abf55af7, 0x9f425fe354428e19); |
x[n++] = make(0, 32767, 0, 0); |
x[n++] = make(1, 32767, 0, 0); |
x[n++] = make(0, 0, 0, 0); |
x[n++] = make(1, 0, 0, 0); |
check(n == sizeof(x) / sizeof(*x)); |
for (i = 0; i < n; i++) { |
for (j = 0; j < n; j++) { |
fadd(x[i], x[j]); |
fsub(x[i], x[j]); |
fmul(x[i], x[j]); |
fdiv(x[i], x[j]); |
} |
} |
} |
} |
void adds(void) |
{ |
// Check shifting and add/sub: |
{ |
int i; |
for (i = -130; i <= 130; i++) { |
int s1 = (uint32_t)i % 3 < 1; |
int s2 = (uint32_t)i % 5 < 2; |
fadd(make(s1, 16384 , 0x502c065e4f71a65d, 0xd2f9bdb031f4f031), |
make(s2, 16384 + i, 0xae267395a9bc1033, 0xb56b5800da1ba448)); |
} |
} |
// Check normalisation: |
{ |
uint64_t a0 = 0xc6bab0a6afbef5ed; |
uint64_t a1 = 0x4f84136c4a2e9b52; |
int ee[] = { 0, 1, 10000 }; |
int e, i; |
for (e = 0; e < sizeof(ee) / sizeof(*ee); e++) { |
int exp = ee[e]; |
fsub(make(0, exp, a1, a0), make(0, 0, 0, 0)); |
for (i = 63; i >= 0; i--) |
fsub(make(0, exp, a1 | (uint64_t)1 << i >> 1, a0), |
make(0, exp, a1 >> i << i, 0)); |
for (i = 63; i >=0; i--) |
fsub(make(0, exp, a1, a0 | (uint64_t)1 << i >> 1), |
make(0, exp, a1, a0 >> i << i)); |
} |
} |
// Carry/overflow from rounding: |
{ |
fadd(make(0, 114, -1, -1), make(0, 1, 0, 0)); |
fadd(make(0, 32766, -1, -1), make(0, 32653, 0, 0)); |
fsub(make(1, 32766, -1, -1), make(0, 32653, 0, 0)); |
} |
} |
void muls(void) |
{ |
int i, j; |
{ |
long double max = make(0, 32766, -1, -1); |
long double min = make(0, 0, 0, 1); |
fmul(max, max); |
fmul(max, min); |
fmul(min, min); |
} |
for (i = 117; i > 0; i--) |
fmul(make(0, 16268, 0x643dcea76edc, 0xe0877a598403627a), |
make(i & 1, i, 0, 0)); |
fmul(make(0, 16383, -1, -3), make(0, 16383, 0, 1)); |
// Round to next exponent: |
fmul(make(0, 16383, -1, -2), make(0, 16383, 0, 1)); |
// Round from subnormal to normal: |
fmul(make(0, 1, -1, -1), make(0, 16382, 0, 0)); |
for (i = 0; i < 2; i++) |
for (j = 0; j < 112; j++) |
fmul(make(0, 16383, (uint64_t)1 << i, 0), |
make(0, 16383, |
j < 64 ? 0 : (uint64_t)1 << (j - 64), |
j < 64 ? (uint64_t)1 << j : 0)); |
} |
void divs(void) |
{ |
int i; |
{ |
long double max = make(0, 32766, -1, -1); |
long double min = make(0, 0, 0, 1); |
fdiv(max, max); |
fdiv(max, min); |
fdiv(min, max); |
fdiv(min, min); |
} |
for (i = 0; i < 64; i++) |
fdiv(make(0, 16383, -1, -1), make(0, 16383, -1, -(uint64_t)1 << i)); |
for (i = 0; i < 48; i++) |
fdiv(make(0, 16383, -1, -1), make(0, 16383, -(uint64_t)1 << i, 0)); |
} |
void cvtlsw(int32_t a) |
{ |
long double f = a; |
u128_t x = copy_ild(f); |
printf("cvtlsw %08lx %016llx%016llx\n", (long)(uint32_t)a, x.x1, x.x0); |
} |
void cvtlsx(int64_t a) |
{ |
long double f = a; |
u128_t x = copy_ild(f); |
printf("cvtlsx %016llx %016llx%016llx\n", |
(long long)(uint64_t)a, x.x1, x.x0); |
} |
void cvtluw(uint32_t a) |
{ |
long double f = a; |
u128_t x = copy_ild(f); |
printf("cvtluw %08lx %016llx%016llx\n", (long)a, x.x1, x.x0); |
} |
void cvtlux(uint64_t a) |
{ |
long double f = a; |
u128_t x = copy_ild(f); |
printf("cvtlux %016llx %016llx%016llx\n", (long long)a, x.x1, x.x0); |
} |
void cvtil(long double a) |
{ |
u128_t x = copy_ild(a); |
int32_t b1 = a; |
int64_t b2 = a; |
uint32_t b3 = a; |
uint64_t b4 = a; |
printf("cvtswl %016llx%016llx %08lx\n", |
x.x1, x.x0, (long)(uint32_t)b1); |
printf("cvtsxl %016llx%016llx %016llx\n", |
x.x1, x.x0, (long long)(uint64_t)b2); |
printf("cvtuwl %016llx%016llx %08lx\n", |
x.x1, x.x0, (long)b3); |
printf("cvtuxl %016llx%016llx %016llx\n", |
x.x1, x.x0, (long long)b4); |
} |
void cvtlf(float a) |
{ |
uint32_t ax = copy_if(a); |
long double b = a; |
u128_t bx = copy_ild(b); |
printf("cvtlf %08lx %016llx%016llx\n", (long)ax, bx.x1, bx.x0); |
} |
void cvtld(double a) |
{ |
uint64_t ax = copy_id(a); |
long double b = a; |
u128_t bx = copy_ild(b); |
printf("cvtld %016llx %016llx%016llx\n", (long long)ax, bx.x1, bx.x0); |
} |
void cvtfl(long double a) |
{ |
u128_t ax = copy_ild(a); |
float b = a; |
uint32_t bx = copy_if(b); |
printf("cvtfl %016llx%016llx %08lx\n", ax.x1, ax.x0, (long)bx); |
} |
void cvtdl(long double a) |
{ |
u128_t ax = copy_ild(a); |
double b = a; |
uint64_t bx = copy_id(b); |
printf("cvtdl %016llx%016llx %016llx\n", ax.x1, ax.x0, (long long)bx); |
} |
void cvts(void) |
{ |
int i, j; |
{ |
uint32_t x = 0xad040c5b; |
cvtlsw(0); |
for (i = 0; i < 31; i++) |
cvtlsw(x >> (31 - i)); |
for (i = 0; i < 31; i++) |
cvtlsw(-(x >> (31 - i))); |
cvtlsw(0x80000000); |
} |
{ |
uint64_t x = 0xb630a248cad9afd2; |
cvtlsx(0); |
for (i = 0; i < 63; i++) |
cvtlsx(x >> (63 - i)); |
for (i = 0; i < 63; i++) |
cvtlsx(-(x >> (63 - i))); |
cvtlsx(0x8000000000000000); |
} |
{ |
uint32_t x = 0xad040c5b; |
cvtluw(0); |
for (i = 0; i < 32; i++) |
cvtluw(x >> (31 - i)); |
} |
{ |
uint64_t x = 0xb630a248cad9afd2; |
cvtlux(0); |
for (i = 0; i < 64; i++) |
cvtlux(x >> (63 - i)); |
} |
for (i = 0; i < 2; i++) { |
cvtil(make(i, 32767, 0, 1)); |
cvtil(make(i, 32767, (uint64_t)1 << 47, 0)); |
cvtil(make(i, 32767, 123, 456)); |
cvtil(make(i, 32767, 0, 0)); |
cvtil(make(i, 16382, -1, -1)); |
cvtil(make(i, 16383, -1, -1)); |
cvtil(make(i, 16384, 0x7fffffffffff, -1)); |
cvtil(make(i, 16384, 0x800000000000, 0)); |
for (j = 0; j < 68; j++) |
cvtil(make(i, 16381 + j, 0xd4822c0a10ec, 0x1fe2f8b2669f5c9d)); |
} |
cvtlf(copy_fi(0x00000000)); |
cvtlf(copy_fi(0x456789ab)); |
cvtlf(copy_fi(0x7f800000)); |
cvtlf(copy_fi(0x7f923456)); |
cvtlf(copy_fi(0x7fdbcdef)); |
cvtlf(copy_fi(0x80000000)); |
cvtlf(copy_fi(0xabcdef12)); |
cvtlf(copy_fi(0xff800000)); |
cvtlf(copy_fi(0xff923456)); |
cvtlf(copy_fi(0xffdbcdef)); |
cvtld(copy_di(0x0000000000000000)); |
cvtld(copy_di(0x456789abcdef0123)); |
cvtld(copy_di(0x7ff0000000000000)); |
cvtld(copy_di(0x7ff123456789abcd)); |
cvtld(copy_di(0x7ffabcdef1234567)); |
cvtld(copy_di(0x8000000000000000)); |
cvtld(copy_di(0xcdef123456789abc)); |
cvtld(copy_di(0xfff0000000000000)); |
cvtld(copy_di(0xfff123456789abcd)); |
cvtld(copy_di(0xfffabcdef1234567)); |
for (i = 0; i < 2; i++) { \ |
cvtfl(make(i, 0, 0, 0)); |
cvtfl(make(i, 16232, -1, -1)); |
cvtfl(make(i, 16233, 0, 0)); |
cvtfl(make(i, 16233, 0, 1)); |
cvtfl(make(i, 16383, 0xab0ffd000000, 0)); |
cvtfl(make(i, 16383, 0xab0ffd000001, 0)); |
cvtfl(make(i, 16383, 0xab0ffeffffff, 0)); |
cvtfl(make(i, 16383, 0xab0fff000000, 0)); |
cvtfl(make(i, 16383, 0xab0fff000001, 0)); |
cvtfl(make(i, 16510, 0xfffffeffffff, -1)); |
cvtfl(make(i, 16510, 0xffffff000000, 0)); |
cvtfl(make(i, 16511, 0, 0)); |
cvtfl(make(i, 32767, 0, 0)); |
cvtfl(make(i, 32767, 0, 1)); |
cvtfl(make(i, 32767, 0x4cbe01ac5f40, 0x75cee3c6afbb00b5)); |
cvtfl(make(i, 32767, 0x800000000000, 1)); |
cvtfl(make(i, 32767, 0xa11caaaf6a52, 0x696033e871eab099)); |
} |
for (i = 0; i < 2; i++) { |
cvtdl(make(i, 0, 0, 0)); |
cvtdl(make(i, 15307, -1, -1)); |
cvtdl(make(i, 15308, 0, 0)); |
cvtdl(make(i, 15308, 0, 1)); |
cvtdl(make(i, 16383, 0xabc123abc0ff, 0xe800000000000000)); |
cvtdl(make(i, 16383, 0xabc123abc0ff, 0xe800000000000001)); |
cvtdl(make(i, 16383, 0xabc123abc0ff, 0xf7ffffffffffffff)); |
cvtdl(make(i, 16383, 0xabc123abc0ff, 0xf800000000000000)); |
cvtdl(make(i, 16383, 0xabc123abc0ff, 0xf800000000000001)); |
cvtdl(make(i, 17406, 0xffffffffffff, 0xf7ffffffffffffff)); |
cvtdl(make(i, 17406, 0xffffffffffff, 0xf800000000000000)); |
cvtdl(make(i, 17407, 0, 0)); |
cvtdl(make(i, 32767, 0, 0)); |
cvtdl(make(i, 32767, 0, 1)); |
cvtdl(make(i, 32767, 0x4cbe01ac5f40, 0x75cee3c6afbb00b5)); |
cvtdl(make(i, 32767, 0x800000000000, 1)); |
cvtdl(make(i, 32767, 0xa11caaaf6a52, 0x696033e871eab099)); |
} |
} |
void tests(void) |
{ |
cmps(); |
nanz(); |
adds(); |
muls(); |
divs(); |
cvts(); |
} |
int main() |
{ |
#ifdef __aarch64__ |
tests(); |
#else |
printf("This test program is intended for a little-endian architecture\n" |
"with an IEEE-standard 128-bit long double.\n"); |
#endif |
return 0; |
} |
/programs/develop/ktcc/trunk/source/libtcc.c |
---|
0,0 → 1,2495 |
/* |
* TCC - Tiny C Compiler |
* |
* Copyright (c) 2001-2004 Fabrice Bellard |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
#include "tcc.h" |
/********************************************************/ |
/* global variables */ |
/* use GNU C extensions */ |
ST_DATA int gnu_ext = 1; |
/* use TinyCC extensions */ |
ST_DATA int tcc_ext = 1; |
/* XXX: get rid of this ASAP */ |
ST_DATA struct TCCState *tcc_state; |
/********************************************************/ |
#ifdef ONE_SOURCE |
#include "tccpp.c" |
#include "tccgen.c" |
#include "tccelf.c" |
#ifdef TCC_IS_NATIVE |
# include "tccrun.c" |
#endif |
#ifdef TCC_TARGET_I386 |
#include "i386-gen.c" |
#endif |
#ifdef TCC_TARGET_ARM |
#include "arm-gen.c" |
#endif |
#ifdef TCC_TARGET_ARM64 |
#include "arm64-gen.c" |
#endif |
#ifdef TCC_TARGET_C67 |
#include "c67-gen.c" |
#endif |
#ifdef TCC_TARGET_X86_64 |
#include "x86_64-gen.c" |
#endif |
#ifdef CONFIG_TCC_ASM |
#include "tccasm.c" |
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 |
#include "i386-asm.c" |
#endif |
#endif |
#ifdef TCC_TARGET_COFF |
#include "tcccoff.c" |
#endif |
#if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS) |
#include "tccpe.c" |
#endif |
#ifdef TCC_TARGET_MEOS |
#include "tccmeos.c" |
#endif |
#endif /* ONE_SOURCE */ |
/********************************************************/ |
#ifndef CONFIG_TCC_ASM |
ST_FUNC void asm_instr(void) |
{ |
tcc_error("inline asm() not supported"); |
} |
ST_FUNC void asm_global_instr(void) |
{ |
tcc_error("inline asm() not supported"); |
} |
#endif |
/********************************************************/ |
#ifdef _WIN32 |
static char *normalize_slashes(char *path) |
{ |
char *p; |
for (p = path; *p; ++p) |
if (*p == '\\') |
*p = '/'; |
return path; |
} |
static HMODULE tcc_module; |
/* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */ |
static void tcc_set_lib_path_w32(TCCState *s) |
{ |
char path[1024], *p; |
GetModuleFileNameA(tcc_module, path, sizeof path); |
p = tcc_basename(normalize_slashes(strlwr(path))); |
if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) |
p -= 5; |
else if (p > path) |
p--; |
*p = 0; |
tcc_set_lib_path(s, path); |
} |
#ifdef TCC_TARGET_PE |
static void tcc_add_systemdir(TCCState *s) |
{ |
char buf[1000]; |
GetSystemDirectory(buf, sizeof buf); |
tcc_add_library_path(s, normalize_slashes(buf)); |
} |
#endif |
#ifndef CONFIG_TCC_STATIC |
void dlclose(void *p) |
{ |
FreeLibrary((HMODULE)p); |
} |
#endif |
#ifdef LIBTCC_AS_DLL |
BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) |
{ |
if (DLL_PROCESS_ATTACH == dwReason) |
tcc_module = hDll; |
return TRUE; |
} |
#endif |
#endif |
/********************************************************/ |
/* copy a string and truncate it. */ |
PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s) |
{ |
char *q, *q_end; |
int c; |
if (buf_size > 0) { |
q = buf; |
q_end = buf + buf_size - 1; |
while (q < q_end) { |
c = *s++; |
if (c == '\0') |
break; |
*q++ = c; |
} |
*q = '\0'; |
} |
return buf; |
} |
/* strcat and truncate. */ |
PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s) |
{ |
int len; |
len = strlen(buf); |
if (len < buf_size) |
pstrcpy(buf + len, buf_size - len, s); |
return buf; |
} |
PUB_FUNC char *pstrncpy(char *out, const char *in, size_t num) |
{ |
memcpy(out, in, num); |
out[num] = '\0'; |
return out; |
} |
/* extract the basename of a file */ |
PUB_FUNC char *tcc_basename(const char *name) |
{ |
char *p = strchr(name, 0); |
while (p > name && !IS_DIRSEP(p[-1])) |
--p; |
return p; |
} |
/* extract extension part of a file |
* |
* (if no extension, return pointer to end-of-string) |
*/ |
PUB_FUNC char *tcc_fileextension (const char *name) |
{ |
char *b = tcc_basename(name); |
char *e = strrchr(b, '.'); |
return e ? e : strchr(b, 0); |
} |
/********************************************************/ |
/* memory management */ |
#undef free |
#undef malloc |
#undef realloc |
#ifndef MEM_DEBUG |
PUB_FUNC void tcc_free(void *ptr) |
{ |
free(ptr); |
} |
PUB_FUNC void *tcc_malloc(unsigned long size) |
{ |
void *ptr; |
ptr = malloc(size); |
if (!ptr && size) |
tcc_error("memory full (malloc)"); |
return ptr; |
} |
PUB_FUNC void *tcc_mallocz(unsigned long size) |
{ |
void *ptr; |
ptr = tcc_malloc(size); |
memset(ptr, 0, size); |
return ptr; |
} |
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) |
{ |
void *ptr1; |
ptr1 = realloc(ptr, size); |
if (!ptr1 && size) |
tcc_error("memory full (realloc)"); |
return ptr1; |
} |
PUB_FUNC char *tcc_strdup(const char *str) |
{ |
char *ptr; |
ptr = tcc_malloc(strlen(str) + 1); |
strcpy(ptr, str); |
return ptr; |
} |
PUB_FUNC void tcc_memstats(int bench) |
{ |
} |
#else |
#define MEM_DEBUG_MAGIC1 0xFEEDDEB1 |
#define MEM_DEBUG_MAGIC2 0xFEEDDEB2 |
#define MEM_DEBUG_FILE_LEN 15 |
struct mem_debug_header { |
size_t magic1; |
size_t size; |
struct mem_debug_header *prev; |
struct mem_debug_header *next; |
size_t line_num; |
char file_name[MEM_DEBUG_FILE_LEN + 1]; |
size_t magic2; |
}; |
typedef struct mem_debug_header mem_debug_header_t; |
static mem_debug_header_t *mem_debug_chain; |
static size_t mem_cur_size; |
static size_t mem_max_size; |
PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) |
{ |
void *ptr; |
int ofs; |
mem_debug_header_t *header; |
ptr = malloc(sizeof(mem_debug_header_t) + size); |
if (!ptr) |
tcc_error("memory full (malloc)"); |
mem_cur_size += size; |
if (mem_cur_size > mem_max_size) |
mem_max_size = mem_cur_size; |
header = (mem_debug_header_t *)ptr; |
header->magic1 = MEM_DEBUG_MAGIC1; |
header->magic2 = MEM_DEBUG_MAGIC2; |
header->size = size; |
header->line_num = line; |
ofs = strlen(file) - MEM_DEBUG_FILE_LEN; |
strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); |
header->file_name[MEM_DEBUG_FILE_LEN] = 0; |
header->next = mem_debug_chain; |
header->prev = NULL; |
if (header->next) |
header->next->prev = header; |
mem_debug_chain = header; |
ptr = (char *)ptr + sizeof(mem_debug_header_t); |
return ptr; |
} |
PUB_FUNC void tcc_free_debug(void *ptr) |
{ |
mem_debug_header_t *header; |
if (!ptr) |
return; |
ptr = (char *)ptr - sizeof(mem_debug_header_t); |
header = (mem_debug_header_t *)ptr; |
if (header->magic1 != MEM_DEBUG_MAGIC1 || |
header->magic2 != MEM_DEBUG_MAGIC2 || |
header->size == (size_t)-1 ) |
{ |
tcc_error("tcc_free check failed"); |
} |
mem_cur_size -= header->size; |
header->size = (size_t)-1; |
if (header->next) |
header->next->prev = header->prev; |
if (header->prev) |
header->prev->next = header->next; |
if (header == mem_debug_chain) |
mem_debug_chain = header->next; |
free(ptr); |
} |
PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) |
{ |
void *ptr; |
ptr = tcc_malloc_debug(size,file,line); |
memset(ptr, 0, size); |
return ptr; |
} |
PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line) |
{ |
mem_debug_header_t *header; |
int mem_debug_chain_update = 0; |
if (!ptr) { |
ptr = tcc_malloc_debug(size, file, line); |
return ptr; |
} |
ptr = (char *)ptr - sizeof(mem_debug_header_t); |
header = (mem_debug_header_t *)ptr; |
if (header->magic1 != MEM_DEBUG_MAGIC1 || |
header->magic2 != MEM_DEBUG_MAGIC2 || |
header->size == (size_t)-1 ) |
{ |
check_error: |
tcc_error("tcc_realloc check failed"); |
} |
mem_debug_chain_update = (header == mem_debug_chain); |
mem_cur_size -= header->size; |
ptr = realloc(ptr, sizeof(mem_debug_header_t) + size); |
if (!ptr) |
tcc_error("memory full (realloc)"); |
header = (mem_debug_header_t *)ptr; |
if (header->magic1 != MEM_DEBUG_MAGIC1 || |
header->magic2 != MEM_DEBUG_MAGIC2) |
{ |
goto check_error; |
} |
mem_cur_size += size; |
if (mem_cur_size > mem_max_size) |
mem_max_size = mem_cur_size; |
header->size = size; |
if (header->next) |
header->next->prev = header; |
if (header->prev) |
header->prev->next = header; |
if (mem_debug_chain_update) |
mem_debug_chain = header; |
ptr = (char *)ptr + sizeof(mem_debug_header_t); |
return ptr; |
} |
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) |
{ |
char *ptr; |
ptr = tcc_malloc_debug(strlen(str) + 1, file, line); |
strcpy(ptr, str); |
return ptr; |
} |
PUB_FUNC void tcc_memstats(int bench) |
{ |
if (mem_cur_size) { |
mem_debug_header_t *header = mem_debug_chain; |
fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n", |
mem_cur_size, mem_max_size); |
while (header) { |
fprintf(stderr, " file %s, line %u: %u bytes\n", |
header->file_name, header->line_num, header->size); |
header = header->next; |
} |
} |
else if (bench) |
fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size); |
} |
#undef MEM_DEBUG_MAGIC1 |
#undef MEM_DEBUG_MAGIC2 |
#undef MEM_DEBUG_FILE_LEN |
#endif |
#define free(p) use_tcc_free(p) |
#define malloc(s) use_tcc_malloc(s) |
#define realloc(p, s) use_tcc_realloc(p, s) |
/********************************************************/ |
/* dynarrays */ |
ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data) |
{ |
int nb, nb_alloc; |
void **pp; |
nb = *nb_ptr; |
pp = *ptab; |
/* every power of two we double array size */ |
if ((nb & (nb - 1)) == 0) { |
if (!nb) |
nb_alloc = 1; |
else |
nb_alloc = nb * 2; |
pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); |
*ptab = pp; |
} |
pp[nb++] = data; |
*nb_ptr = nb; |
} |
ST_FUNC void dynarray_reset(void *pp, int *n) |
{ |
void **p; |
for (p = *(void***)pp; *n; ++p, --*n) |
if (*p) |
tcc_free(*p); |
tcc_free(*(void**)pp); |
*(void**)pp = NULL; |
} |
static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in) |
{ |
const char *p; |
do { |
int c; |
CString str; |
cstr_new(&str); |
for (p = in; c = *p, c != '\0' && c != PATHSEP; ++p) { |
if (c == '{' && p[1] && p[2] == '}') { |
c = p[1], p += 2; |
if (c == 'B') |
cstr_cat(&str, s->tcc_lib_path, -1); |
} else { |
cstr_ccat(&str, c); |
} |
} |
cstr_ccat(&str, '\0'); |
dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data)); |
cstr_free(&str); |
in = p+1; |
} while (*p); |
} |
/********************************************************/ |
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) |
{ |
Section *sec; |
sec = tcc_mallocz(sizeof(Section) + strlen(name)); |
strcpy(sec->name, name); |
sec->sh_type = sh_type; |
sec->sh_flags = sh_flags; |
switch(sh_type) { |
case SHT_HASH: |
case SHT_REL: |
case SHT_RELA: |
case SHT_DYNSYM: |
case SHT_SYMTAB: |
case SHT_DYNAMIC: |
sec->sh_addralign = 4; |
break; |
case SHT_STRTAB: |
sec->sh_addralign = 1; |
break; |
default: |
sec->sh_addralign = PTR_SIZE; /* gcc/pcc default aligment */ |
break; |
} |
if (sh_flags & SHF_PRIVATE) { |
dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec); |
} else { |
sec->sh_num = s1->nb_sections; |
dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec); |
} |
return sec; |
} |
static void free_section(Section *s) |
{ |
tcc_free(s->data); |
} |
/* realloc section and set its content to zero */ |
ST_FUNC void section_realloc(Section *sec, unsigned long new_size) |
{ |
unsigned long size; |
unsigned char *data; |
size = sec->data_allocated; |
if (size == 0) |
size = 1; |
while (size < new_size) |
size = size * 2; |
data = tcc_realloc(sec->data, size); |
memset(data + sec->data_allocated, 0, size - sec->data_allocated); |
sec->data = data; |
sec->data_allocated = size; |
} |
/* reserve at least 'size' bytes in section 'sec' from |
sec->data_offset. */ |
ST_FUNC void *section_ptr_add(Section *sec, addr_t size) |
{ |
size_t offset, offset1; |
offset = sec->data_offset; |
offset1 = offset + size; |
if (offset1 > sec->data_allocated) |
section_realloc(sec, offset1); |
sec->data_offset = offset1; |
return sec->data + offset; |
} |
/* reserve at least 'size' bytes from section start */ |
ST_FUNC void section_reserve(Section *sec, unsigned long size) |
{ |
if (size > sec->data_allocated) |
section_realloc(sec, size); |
if (size > sec->data_offset) |
sec->data_offset = size; |
} |
/* return a reference to a section, and create it if it does not |
exists */ |
ST_FUNC Section *find_section(TCCState *s1, const char *name) |
{ |
Section *sec; |
int i; |
for(i = 1; i < s1->nb_sections; i++) { |
sec = s1->sections[i]; |
if (!strcmp(name, sec->name)) |
return sec; |
} |
/* sections are created as PROGBITS */ |
return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC); |
} |
/* update sym->c so that it points to an external symbol in section |
'section' with value 'value' */ |
ST_FUNC void put_extern_sym2(Sym *sym, Section *section, |
addr_t value, unsigned long size, |
int can_add_underscore) |
{ |
int sym_type, sym_bind, sh_num, info, other; |
ElfW(Sym) *esym; |
const char *name; |
char buf1[256]; |
#ifdef CONFIG_TCC_BCHECK |
char buf[32]; |
#endif |
if (section == NULL) |
sh_num = SHN_UNDEF; |
else if (section == SECTION_ABS) |
sh_num = SHN_ABS; |
else |
sh_num = section->sh_num; |
if ((sym->type.t & VT_BTYPE) == VT_FUNC) { |
sym_type = STT_FUNC; |
} else if ((sym->type.t & VT_BTYPE) == VT_VOID) { |
sym_type = STT_NOTYPE; |
} else { |
sym_type = STT_OBJECT; |
} |
if (sym->type.t & VT_STATIC) |
sym_bind = STB_LOCAL; |
else { |
if (sym->type.t & VT_WEAK) |
sym_bind = STB_WEAK; |
else |
sym_bind = STB_GLOBAL; |
} |
if (!sym->c) { |
name = get_tok_str(sym->v, NULL); |
#ifdef CONFIG_TCC_BCHECK |
if (tcc_state->do_bounds_check) { |
/* XXX: avoid doing that for statics ? */ |
/* if bound checking is activated, we change some function |
names by adding the "__bound" prefix */ |
switch(sym->v) { |
#ifdef TCC_TARGET_PE |
/* XXX: we rely only on malloc hooks */ |
case TOK_malloc: |
case TOK_free: |
case TOK_realloc: |
case TOK_memalign: |
case TOK_calloc: |
#endif |
case TOK_memcpy: |
case TOK_memmove: |
case TOK_memset: |
case TOK_strlen: |
case TOK_strcpy: |
case TOK_alloca: |
strcpy(buf, "__bound_"); |
strcat(buf, name); |
name = buf; |
break; |
} |
} |
#endif |
other = 0; |
#ifdef TCC_TARGET_PE |
if (sym->type.t & VT_EXPORT) |
other |= ST_PE_EXPORT; |
if (sym_type == STT_FUNC && sym->type.ref) { |
Sym *ref = sym->type.ref; |
if (ref->a.func_export) |
other |= ST_PE_EXPORT; |
if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { |
sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); |
name = buf1; |
other |= ST_PE_STDCALL; |
can_add_underscore = 0; |
} |
} else { |
if (find_elf_sym(tcc_state->dynsymtab_section, name)) |
other |= ST_PE_IMPORT; |
if (sym->type.t & VT_IMPORT) |
other |= ST_PE_IMPORT; |
} |
#else |
if (! (sym->type.t & VT_STATIC)) |
other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT; |
#endif |
if (tcc_state->leading_underscore && can_add_underscore) { |
buf1[0] = '_'; |
pstrcpy(buf1 + 1, sizeof(buf1) - 1, name); |
name = buf1; |
} |
if (sym->asm_label) { |
name = get_tok_str(sym->asm_label, NULL); |
} |
info = ELFW(ST_INFO)(sym_bind, sym_type); |
sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name); |
} else { |
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; |
esym->st_value = value; |
esym->st_size = size; |
esym->st_shndx = sh_num; |
} |
} |
ST_FUNC void put_extern_sym(Sym *sym, Section *section, |
addr_t value, unsigned long size) |
{ |
put_extern_sym2(sym, section, value, size, 1); |
} |
/* add a new relocation entry to symbol 'sym' in section 's' */ |
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, |
addr_t addend) |
{ |
int c = 0; |
if (sym) { |
if (0 == sym->c) |
put_extern_sym(sym, NULL, 0, 0); |
c = sym->c; |
} |
/* now we can add ELF relocation info */ |
put_elf_reloca(symtab_section, s, offset, type, c, addend); |
} |
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) |
{ |
greloca(s, sym, offset, type, 0); |
} |
/********************************************************/ |
static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) |
{ |
int len; |
len = strlen(buf); |
vsnprintf(buf + len, buf_size - len, fmt, ap); |
} |
static void strcat_printf(char *buf, int buf_size, const char *fmt, ...) |
{ |
va_list ap; |
va_start(ap, fmt); |
strcat_vprintf(buf, buf_size, fmt, ap); |
va_end(ap); |
} |
static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) |
{ |
char buf[2048]; |
BufferedFile **pf, *f; |
buf[0] = '\0'; |
/* use upper file if inline ":asm:" or token ":paste:" */ |
for (f = file; f && f->filename[0] == ':'; f = f->prev) |
; |
if (f) { |
for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++) |
strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", |
(*pf)->filename, (*pf)->line_num); |
if (f->line_num > 0) { |
strcat_printf(buf, sizeof(buf), "%s:%d: ", |
f->filename, f->line_num); |
} else { |
strcat_printf(buf, sizeof(buf), "%s: ", |
f->filename); |
} |
} else { |
strcat_printf(buf, sizeof(buf), "tcc: "); |
} |
if (is_warning) |
strcat_printf(buf, sizeof(buf), "warning: "); |
else |
strcat_printf(buf, sizeof(buf), "error: "); |
strcat_vprintf(buf, sizeof(buf), fmt, ap); |
if (!s1->error_func) { |
/* default case: stderr */ |
if (s1->ppfp) /* print a newline during tcc -E */ |
fprintf(s1->ppfp, "\n"), fflush(s1->ppfp); |
fprintf(stderr, "%s\n", buf); |
fflush(stderr); /* print error/warning now (win32) */ |
} else { |
s1->error_func(s1->error_opaque, buf); |
} |
if (!is_warning || s1->warn_error) |
s1->nb_errors++; |
} |
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, |
void (*error_func)(void *opaque, const char *msg)) |
{ |
s->error_opaque = error_opaque; |
s->error_func = error_func; |
} |
/* error without aborting current compilation */ |
PUB_FUNC void tcc_error_noabort(const char *fmt, ...) |
{ |
TCCState *s1 = tcc_state; |
va_list ap; |
va_start(ap, fmt); |
error1(s1, 0, fmt, ap); |
va_end(ap); |
} |
PUB_FUNC void tcc_error(const char *fmt, ...) |
{ |
TCCState *s1 = tcc_state; |
va_list ap; |
va_start(ap, fmt); |
error1(s1, 0, fmt, ap); |
va_end(ap); |
/* better than nothing: in some cases, we accept to handle errors */ |
if (s1->error_set_jmp_enabled) { |
longjmp(s1->error_jmp_buf, 1); |
} else { |
/* XXX: eliminate this someday */ |
exit(1); |
} |
} |
PUB_FUNC void tcc_warning(const char *fmt, ...) |
{ |
TCCState *s1 = tcc_state; |
va_list ap; |
if (s1->warn_none) |
return; |
va_start(ap, fmt); |
error1(s1, 1, fmt, ap); |
va_end(ap); |
} |
/********************************************************/ |
/* I/O layer */ |
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen) |
{ |
BufferedFile *bf; |
int buflen = initlen ? initlen : IO_BUF_SIZE; |
bf = tcc_mallocz(sizeof(BufferedFile) + buflen); |
bf->buf_ptr = bf->buffer; |
bf->buf_end = bf->buffer + initlen; |
bf->buf_end[0] = CH_EOB; /* put eob symbol */ |
pstrcpy(bf->filename, sizeof(bf->filename), filename); |
#ifdef _WIN32 |
normalize_slashes(bf->filename); |
#endif |
bf->line_num = 1; |
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; |
bf->fd = -1; |
bf->prev = file; |
file = bf; |
} |
ST_FUNC void tcc_close(void) |
{ |
BufferedFile *bf = file; |
if (bf->fd > 0) { |
close(bf->fd); |
total_lines += bf->line_num; |
} |
file = bf->prev; |
tcc_free(bf); |
} |
ST_FUNC int tcc_open(TCCState *s1, const char *filename) |
{ |
int fd; |
if (strcmp(filename, "-") == 0) |
fd = 0, filename = "<stdin>"; |
else |
fd = open(filename, O_RDONLY | O_BINARY); |
if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3) |
printf("%s %*s%s\n", fd < 0 ? "nf":"->", |
(int)(s1->include_stack_ptr - s1->include_stack), "", filename); |
if (fd < 0) |
return -1; |
tcc_open_bf(s1, filename, 0); |
file->fd = fd; |
return fd; |
} |
/* compile the C file opened in 'file'. Return non zero if errors. */ |
static int tcc_compile(TCCState *s1) |
{ |
Sym *define_start; |
char buf[512]; |
volatile int section_sym; |
#ifdef INC_DEBUG |
printf("%s: **** new file\n", file->filename); |
#endif |
preprocess_init(s1); |
cur_text_section = NULL; |
funcname = ""; |
anon_sym = SYM_FIRST_ANOM; |
/* file info: full path + filename */ |
section_sym = 0; /* avoid warning */ |
if (s1->do_debug) { |
section_sym = put_elf_sym(symtab_section, 0, 0, |
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, |
text_section->sh_num, NULL); |
getcwd(buf, sizeof(buf)); |
#ifdef _WIN32 |
normalize_slashes(buf); |
#endif |
pstrcat(buf, sizeof(buf), "/"); |
put_stabs_r(buf, N_SO, 0, 0, |
text_section->data_offset, text_section, section_sym); |
put_stabs_r(file->filename, N_SO, 0, 0, |
text_section->data_offset, text_section, section_sym); |
} |
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL |
symbols can be safely used */ |
put_elf_sym(symtab_section, 0, 0, |
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, |
SHN_ABS, file->filename); |
/* define some often used types */ |
int_type.t = VT_INT; |
char_pointer_type.t = VT_BYTE; |
mk_pointer(&char_pointer_type); |
#if PTR_SIZE == 4 |
size_type.t = VT_INT; |
#else |
size_type.t = VT_LLONG; |
#endif |
func_old_type.t = VT_FUNC; |
func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); |
#ifdef TCC_TARGET_ARM |
arm_init(s1); |
#endif |
#if 0 |
/* define 'void *alloca(unsigned int)' builtin function */ |
{ |
Sym *s1; |
p = anon_sym++; |
sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW); |
s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); |
s1->next = NULL; |
sym->next = s1; |
sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); |
} |
#endif |
define_start = define_stack; |
nocode_wanted = 1; |
if (setjmp(s1->error_jmp_buf) == 0) { |
s1->nb_errors = 0; |
s1->error_set_jmp_enabled = 1; |
ch = file->buf_ptr[0]; |
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; |
parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; |
next(); |
decl(VT_CONST); |
if (tok != TOK_EOF) |
expect("declaration"); |
check_vstack(); |
/* end of translation unit info */ |
if (s1->do_debug) { |
put_stabs_r(NULL, N_SO, 0, 0, |
text_section->data_offset, text_section, section_sym); |
} |
} |
s1->error_set_jmp_enabled = 0; |
/* reset define stack, but leave -Dsymbols (may be incorrect if |
they are undefined) */ |
free_defines(define_start); |
gen_inline_functions(); |
sym_pop(&global_stack, NULL); |
sym_pop(&local_stack, NULL); |
return s1->nb_errors != 0 ? -1 : 0; |
} |
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str) |
{ |
int len, ret; |
len = strlen(str); |
tcc_open_bf(s, "<string>", len); |
memcpy(file->buffer, str, len); |
ret = tcc_compile(s); |
tcc_close(); |
return ret; |
} |
/* define a preprocessor symbol. A value can also be provided with the '=' operator */ |
LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) |
{ |
int len1, len2; |
/* default value */ |
if (!value) |
value = "1"; |
len1 = strlen(sym); |
len2 = strlen(value); |
/* init file structure */ |
tcc_open_bf(s1, "<define>", len1 + len2 + 1); |
memcpy(file->buffer, sym, len1); |
file->buffer[len1] = ' '; |
memcpy(file->buffer + len1 + 1, value, len2); |
/* parse with define parser */ |
ch = file->buf_ptr[0]; |
next_nomacro(); |
parse_define(); |
tcc_close(); |
} |
/* undefine a preprocessor symbol */ |
LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym) |
{ |
TokenSym *ts; |
Sym *s; |
ts = tok_alloc(sym, strlen(sym)); |
s = define_find(ts->tok); |
/* undefine symbol by putting an invalid name */ |
if (s) |
define_undef(s); |
} |
/* cleanup all static data used during compilation */ |
static void tcc_cleanup(void) |
{ |
if (NULL == tcc_state) |
return; |
tcc_state = NULL; |
preprocess_delete(); |
/* free sym_pools */ |
dynarray_reset(&sym_pools, &nb_sym_pools); |
/* reset symbol stack */ |
sym_free_first = NULL; |
} |
LIBTCCAPI TCCState *tcc_new(void) |
{ |
TCCState *s; |
char buffer[100]; |
int a,b,c; |
tcc_cleanup(); |
s = tcc_mallocz(sizeof(TCCState)); |
if (!s) |
return NULL; |
tcc_state = s; |
#ifdef _WIN32 |
tcc_set_lib_path_w32(s); |
#else |
tcc_set_lib_path(s, CONFIG_TCCDIR); |
#endif |
s->output_type = 0; |
preprocess_new(); |
s->include_stack_ptr = s->include_stack; |
/* we add dummy defines for some special macros to speed up tests |
and to have working defined() */ |
define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL); |
define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); |
define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); |
define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); |
/* define __TINYC__ 92X */ |
sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c); |
sprintf(buffer, "%d", a*10000 + b*100 + c); |
tcc_define_symbol(s, "__TINYC__", buffer); |
/* standard defines */ |
tcc_define_symbol(s, "__STDC__", NULL); |
tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); |
tcc_define_symbol(s, "__STDC_HOSTED__", NULL); |
/* target defines */ |
#if defined(TCC_TARGET_I386) |
tcc_define_symbol(s, "__i386__", NULL); |
tcc_define_symbol(s, "__i386", NULL); |
tcc_define_symbol(s, "i386", NULL); |
#elif defined(TCC_TARGET_X86_64) |
tcc_define_symbol(s, "__x86_64__", NULL); |
#elif defined(TCC_TARGET_ARM) |
tcc_define_symbol(s, "__ARM_ARCH_4__", NULL); |
tcc_define_symbol(s, "__arm_elf__", NULL); |
tcc_define_symbol(s, "__arm_elf", NULL); |
tcc_define_symbol(s, "arm_elf", NULL); |
tcc_define_symbol(s, "__arm__", NULL); |
tcc_define_symbol(s, "__arm", NULL); |
tcc_define_symbol(s, "arm", NULL); |
tcc_define_symbol(s, "__APCS_32__", NULL); |
tcc_define_symbol(s, "__ARMEL__", NULL); |
#if defined(TCC_ARM_EABI) |
tcc_define_symbol(s, "__ARM_EABI__", NULL); |
#endif |
#if defined(TCC_ARM_HARDFLOAT) |
s->float_abi = ARM_HARD_FLOAT; |
tcc_define_symbol(s, "__ARM_PCS_VFP", NULL); |
#else |
s->float_abi = ARM_SOFTFP_FLOAT; |
#endif |
#elif defined(TCC_TARGET_ARM64) |
tcc_define_symbol(s, "__aarch64__", NULL); |
#endif |
#ifdef TCC_TARGET_PE |
tcc_define_symbol(s, "_WIN32", NULL); |
# ifdef TCC_TARGET_X86_64 |
tcc_define_symbol(s, "_WIN64", NULL); |
# endif |
#else |
tcc_define_symbol(s, "__unix__", NULL); |
tcc_define_symbol(s, "__unix", NULL); |
tcc_define_symbol(s, "unix", NULL); |
# if defined(__linux__) |
tcc_define_symbol(s, "__linux__", NULL); |
tcc_define_symbol(s, "__linux", NULL); |
# endif |
# if defined(__FreeBSD__) |
# define str(s) #s |
tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__)); |
# undef str |
# endif |
# if defined(__FreeBSD_kernel__) |
tcc_define_symbol(s, "__FreeBSD_kernel__", NULL); |
# endif |
#endif |
# if defined(__NetBSD__) |
# define str(s) #s |
tcc_define_symbol(s, "__NetBSD__", str( __NetBSD__)); |
# undef str |
# endif |
/* TinyCC & gcc defines */ |
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 |
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long"); |
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long"); |
#else |
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long"); |
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long"); |
#endif |
#ifdef TCC_TARGET_PE |
tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); |
tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short"); |
#else |
tcc_define_symbol(s, "__WCHAR_TYPE__", "int"); |
/* wint_t is unsigned int by default, but (signed) int on BSDs |
and unsigned short on windows. Other OSes might have still |
other conventions, sigh. */ |
#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__) |
tcc_define_symbol(s, "__WINT_TYPE__", "int"); |
#else |
tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int"); |
#endif |
#endif |
#ifndef TCC_TARGET_PE |
/* glibc defines */ |
tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)"); |
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW"); |
/* paths for crt objects */ |
tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); |
#endif |
/* no section zero */ |
dynarray_add((void ***)&s->sections, &s->nb_sections, NULL); |
/* create standard sections */ |
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); |
/* symbols are always generated for linking stage */ |
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, |
".strtab", |
".hashtab", SHF_PRIVATE); |
strtab_section = symtab_section->link; |
s->symtab = symtab_section; |
/* private symbol table for dynamic symbols */ |
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE, |
".dynstrtab", |
".dynhashtab", SHF_PRIVATE); |
s->alacarte_link = 1; |
s->nocommon = 1; |
s->warn_implicit_function_declaration = 1; |
#ifdef CHAR_IS_UNSIGNED |
s->char_is_unsigned = 1; |
#endif |
/* enable this if you want symbols with leading underscore on windows: */ |
#if 0 /* def TCC_TARGET_PE */ |
s->leading_underscore = 1; |
#endif |
#if 0 /* TCC_TARGET_MEOS */ |
s->leading_underscore = 1; |
#endif |
#ifdef TCC_TARGET_I386 |
s->seg_size = 32; |
#endif |
#ifdef TCC_IS_NATIVE |
s->runtime_main = "main"; |
#endif |
return s; |
} |
LIBTCCAPI void tcc_delete(TCCState *s1) |
{ |
int i; |
int bench = s1->do_bench; |
tcc_cleanup(); |
/* close a preprocessor output */ |
if (s1->ppfp && s1->ppfp != stdout) |
fclose(s1->ppfp); |
if (s1->dffp && s1->dffp != s1->ppfp) |
fclose(s1->dffp); |
/* free all sections */ |
for(i = 1; i < s1->nb_sections; i++) |
free_section(s1->sections[i]); |
dynarray_reset(&s1->sections, &s1->nb_sections); |
for(i = 0; i < s1->nb_priv_sections; i++) |
free_section(s1->priv_sections[i]); |
dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); |
/* free any loaded DLLs */ |
#ifdef TCC_IS_NATIVE |
for ( i = 0; i < s1->nb_loaded_dlls; i++) { |
DLLReference *ref = s1->loaded_dlls[i]; |
if ( ref->handle ) |
dlclose(ref->handle); |
} |
#endif |
/* free loaded dlls array */ |
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); |
/* free library paths */ |
dynarray_reset(&s1->library_paths, &s1->nb_library_paths); |
dynarray_reset(&s1->crt_paths, &s1->nb_crt_paths); |
/* free include paths */ |
dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes); |
dynarray_reset(&s1->include_paths, &s1->nb_include_paths); |
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); |
tcc_free(s1->tcc_lib_path); |
tcc_free(s1->soname); |
tcc_free(s1->rpath); |
tcc_free(s1->init_symbol); |
tcc_free(s1->fini_symbol); |
tcc_free(s1->outfile); |
tcc_free(s1->deps_outfile); |
dynarray_reset(&s1->files, &s1->nb_files); |
dynarray_reset(&s1->target_deps, &s1->nb_target_deps); |
dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs); |
#ifdef TCC_IS_NATIVE |
# ifdef HAVE_SELINUX |
munmap (s1->write_mem, s1->mem_size); |
munmap (s1->runtime_mem, s1->mem_size); |
# else |
tcc_free(s1->runtime_mem); |
# endif |
#endif |
tcc_free(s1->sym_attrs); |
tcc_free(s1); |
tcc_memstats(bench); |
} |
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) |
{ |
tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname); |
return 0; |
} |
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) |
{ |
tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); |
return 0; |
} |
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags, int filetype) |
{ |
ElfW(Ehdr) ehdr; |
int fd, ret, size; |
parse_flags = 0; |
#ifdef CONFIG_TCC_ASM |
/* if .S file, define __ASSEMBLER__ like gcc does */ |
if ((filetype == TCC_FILETYPE_ASM) || (filetype == TCC_FILETYPE_ASM_PP)) { |
tcc_define_symbol(s1, "__ASSEMBLER__", NULL); |
parse_flags = PARSE_FLAG_ASM_FILE; |
} |
#endif |
/* open the file */ |
ret = tcc_open(s1, filename); |
if (ret < 0) { |
if (flags & AFF_PRINT_ERROR) |
tcc_error_noabort("file '%s' not found", filename); |
return ret; |
} |
/* update target deps */ |
dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, |
tcc_strdup(filename)); |
if (flags & AFF_PREPROCESS) { |
ret = tcc_preprocess(s1); |
goto the_end; |
} |
if (filetype == TCC_FILETYPE_C) { |
/* C file assumed */ |
ret = tcc_compile(s1); |
goto the_end; |
} |
#ifdef CONFIG_TCC_ASM |
if (filetype == TCC_FILETYPE_ASM_PP) { |
/* non preprocessed assembler */ |
ret = tcc_assemble(s1, 1); |
goto the_end; |
} |
if (filetype == TCC_FILETYPE_ASM) { |
/* preprocessed assembler */ |
ret = tcc_assemble(s1, 0); |
goto the_end; |
} |
#endif |
fd = file->fd; |
/* assume executable format: auto guess file type */ |
size = read(fd, &ehdr, sizeof(ehdr)); |
lseek(fd, 0, SEEK_SET); |
if (size <= 0) { |
tcc_error_noabort("could not read header"); |
goto the_end; |
} |
if (size == sizeof(ehdr) && |
ehdr.e_ident[0] == ELFMAG0 && |
ehdr.e_ident[1] == ELFMAG1 && |
ehdr.e_ident[2] == ELFMAG2 && |
ehdr.e_ident[3] == ELFMAG3) { |
/* do not display line number if error */ |
file->line_num = 0; |
if (ehdr.e_type == ET_REL) { |
ret = tcc_load_object_file(s1, fd, 0); |
goto the_end; |
} |
#if !defined(TCC_TARGET_PE) && !defined(TCC_TARGET_MEOS) |
if (ehdr.e_type == ET_DYN) { |
if (s1->output_type == TCC_OUTPUT_MEMORY) { |
#ifdef TCC_IS_NATIVE |
void *h; |
h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); |
if (h) |
#endif |
ret = 0; |
} else { |
ret = tcc_load_dll(s1, fd, filename, |
(flags & AFF_REFERENCED_DLL) != 0); |
} |
goto the_end; |
} |
#endif |
tcc_error_noabort("unrecognized ELF file"); |
goto the_end; |
} |
if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { |
file->line_num = 0; /* do not display line number if error */ |
ret = tcc_load_archive(s1, fd); |
goto the_end; |
} |
#ifdef TCC_TARGET_COFF |
if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { |
ret = tcc_load_coff(s1, fd); |
goto the_end; |
} |
#endif |
#if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS) |
ret = pe_load_file(s1, filename, fd); |
#else |
/* as GNU ld, consider it is an ld script if not recognized */ |
ret = tcc_load_ldscript(s1); |
#endif |
if (ret < 0) |
tcc_error_noabort("unrecognized file type"); |
the_end: |
tcc_close(); |
return ret; |
} |
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename, int filetype) |
{ |
if (s->output_type == TCC_OUTPUT_PREPROCESS) |
return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS, filetype); |
else |
return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR, filetype); |
} |
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) |
{ |
tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname); |
return 0; |
} |
static int tcc_add_library_internal(TCCState *s, const char *fmt, |
const char *filename, int flags, char **paths, int nb_paths) |
{ |
char buf[1024]; |
int i; |
for(i = 0; i < nb_paths; i++) { |
snprintf(buf, sizeof(buf), fmt, paths[i], filename); |
//printf("added lib [%s]\n", buf); |
if (tcc_add_file_internal(s, buf, flags, TCC_FILETYPE_BINARY) == 0) |
return 0; |
} |
return -1; |
} |
#if !defined(TCC_TARGET_PE) && !defined(TCC_TARGET_MEOS) |
/* find and load a dll. Return non zero if not found */ |
/* XXX: add '-rpath' option support ? */ |
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags) |
{ |
return tcc_add_library_internal(s, "%s/%s", filename, flags, |
s->library_paths, s->nb_library_paths); |
} |
#endif |
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename) |
{ |
if (-1 == tcc_add_library_internal(s, "%s/%s", |
filename, 0, s->crt_paths, s->nb_crt_paths)) |
tcc_error_noabort("file '%s' not found", filename); |
return 0; |
} |
/* the library name is the same as the argument of the '-l' option */ |
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) |
{ |
#if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS) |
const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL }; |
const char **pp = s->static_link ? libs + 4 : libs; |
#else |
const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL }; |
const char **pp = s->static_link ? libs + 1 : libs; |
#endif |
while (*pp) { |
if (0 == tcc_add_library_internal(s, *pp, |
libraryname, 0, s->library_paths, s->nb_library_paths)) |
return 0; |
++pp; |
} |
return -1; |
} |
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname) |
{ |
int ret = tcc_add_library(s, libname); |
if (ret < 0) |
tcc_error_noabort("cannot find library 'lib%s'", libname); |
return ret; |
} |
/* habdle #pragma comment(lib,) */ |
ST_FUNC void tcc_add_pragma_libs(TCCState *s1) |
{ |
int i; |
for (i = 0; i < s1->nb_pragma_libs; i++) |
tcc_add_library_err(s1, s1->pragma_libs[i]); |
} |
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val) |
{ |
#if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS) |
/* On x86_64 'val' might not be reachable with a 32bit offset. |
So it is handled here as if it were in a DLL. */ |
pe_putimport(s, 0, name, (uintptr_t)val); |
#else |
add_elf_sym(symtab_section, (uintptr_t)val, 0, |
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, |
SHN_ABS, name); |
#endif |
return 0; |
} |
/* Windows stat* ( https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx ): |
* - st_gid, st_ino, st_uid: only valid on "unix" file systems (not FAT, NTFS, etc) |
* - st_atime, st_ctime: not valid on FAT, valid on NTFS. |
* - Other fields should be reasonably compatible (and S_ISDIR should work). |
* |
* BY_HANDLE_FILE_INFORMATION ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788%28v=vs.85%29.aspx ): |
* - File index (combined nFileIndexHigh and nFileIndexLow) _may_ change when the file is opened. |
* - But on NTFS: it's guaranteed to be the same value until the file is deleted. |
* - On windows server 2012 there's a 128b file id, and the 64b one via |
* nFileIndex* is not guaranteed to be unique. |
* |
* - MS Docs suggest to that volume number with the file index could be used to |
* check if two handles refer to the same file. |
*/ |
#ifndef _WIN32 |
typedef struct stat file_info_t; |
#else |
typedef BY_HANDLE_FILE_INFORMATION file_info_t; |
#endif |
int get_file_info(const char *fname, file_info_t *out_info) |
{ |
#ifndef _WIN32 |
return stat(fname, out_info); |
#else |
int rv = 1; |
HANDLE h = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, |
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL); |
if (h != INVALID_HANDLE_VALUE) { |
rv = !GetFileInformationByHandle(h, out_info); |
CloseHandle(h); |
} |
return rv; |
#endif |
} |
int is_dir(file_info_t *info) |
{ |
#ifndef _WIN32 |
return S_ISDIR(info->st_mode); |
#else |
return (info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == |
FILE_ATTRIBUTE_DIRECTORY; |
#endif |
} |
int is_same_file(const file_info_t *fi1, const file_info_t *fi2) |
{ |
#ifndef _WIN32 |
return fi1->st_dev == fi2->st_dev && |
fi1->st_ino == fi2->st_ino; |
#else |
return fi1->dwVolumeSerialNumber == fi2->dwVolumeSerialNumber && |
fi1->nFileIndexHigh == fi2->nFileIndexHigh && |
fi1->nFileIndexLow == fi2->nFileIndexLow; |
#endif |
} |
static void |
tcc_normalize_inc_dirs_aux(file_info_t *stats, size_t *pnum, char **path) |
{ |
size_t i, num = *pnum; |
if (get_file_info(*path, &stats[num]) || !is_dir(&stats[num])) |
goto remove; |
for (i = 0; i < num; i++) |
if (is_same_file(&stats[i], &stats[num])) |
goto remove; |
*pnum = num + 1; |
return; |
remove: |
tcc_free(*path); |
*path = 0; |
} |
/* Remove non-existent and duplicate directories from include paths. */ |
ST_FUNC void tcc_normalize_inc_dirs(TCCState *s) |
{ |
file_info_t *stats = |
tcc_malloc(((size_t)s->nb_sysinclude_paths + s->nb_include_paths) * |
sizeof(*stats)); |
size_t i, num = 0; |
for (i = 0; i < s->nb_sysinclude_paths; i++) |
tcc_normalize_inc_dirs_aux(stats, &num, &s->sysinclude_paths[i]); |
for (i = 0; i < s->nb_include_paths; i++) |
tcc_normalize_inc_dirs_aux(stats, &num, &s->include_paths[i]); |
tcc_free(stats); |
} |
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) |
{ |
s->output_type = output_type; |
if (s->output_type == TCC_OUTPUT_PREPROCESS) { |
if (!s->outfile) { |
s->ppfp = stdout; |
} else { |
s->ppfp = fopen(s->outfile, "w"); |
if (!s->ppfp) |
tcc_error("could not write '%s'", s->outfile); |
} |
s->dffp = s->ppfp; |
if (s->dflag == 'M') |
s->ppfp = NULL; |
} |
if (s->option_C && !s->ppfp) |
s->option_C = 0; |
if (!s->nostdinc) { |
/* default include paths */ |
/* -isystem paths have already been handled */ |
tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS); |
} |
/* if bound checking, then add corresponding sections */ |
#ifdef CONFIG_TCC_BCHECK |
if (s->do_bounds_check) { |
/* define symbol */ |
tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL); |
/* create bounds sections */ |
bounds_section = new_section(s, ".bounds", |
SHT_PROGBITS, SHF_ALLOC); |
lbounds_section = new_section(s, ".lbounds", |
SHT_PROGBITS, SHF_ALLOC); |
} |
#endif |
if (s->char_is_unsigned) { |
tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL); |
} |
/* add debug sections */ |
if (s->do_debug) { |
/* stab symbols */ |
stab_section = new_section(s, ".stab", SHT_PROGBITS, 0); |
stab_section->sh_entsize = sizeof(Stab_Sym); |
stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0); |
put_elf_str(stabstr_section, ""); |
stab_section->link = stabstr_section; |
/* put first entry */ |
put_stabs("", 0, 0, 0, 0); |
} |
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS); |
#ifdef TCC_TARGET_PE |
# ifdef _WIN32 |
tcc_add_systemdir(s); |
# endif |
#elif defined(TCC_TARGET_MEOS) |
if (s->output_type != TCC_OUTPUT_OBJ && !s->nostdlib) |
{ |
tcc_add_crt(s,"start.o"); |
// tcc_add_library(s,"ck"); // adding libck.a dont work, because need to be added last |
} |
#else |
/* add libc crt1/crti objects */ |
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && |
!s->nostdlib) { |
if (output_type != TCC_OUTPUT_DLL) |
tcc_add_crt(s, "crt1.o"); |
tcc_add_crt(s, "crti.o"); |
} |
#endif |
#ifdef CONFIG_TCC_BCHECK |
if (s->do_bounds_check && (output_type == TCC_OUTPUT_EXE)) |
{ |
/* force a bcheck.o linking */ |
addr_t func = TOK___bound_init; |
Sym *sym = external_global_sym(func, &func_old_type, 0); |
if (!sym->c) |
put_extern_sym(sym, NULL, 0, 0); |
} |
#endif |
if (s->normalize_inc_dirs) |
tcc_normalize_inc_dirs(s); |
if (s->output_type == TCC_OUTPUT_PREPROCESS) |
print_defines(); |
return 0; |
} |
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path) |
{ |
tcc_free(s->tcc_lib_path); |
s->tcc_lib_path = tcc_strdup(path); |
} |
#define WD_ALL 0x0001 /* warning is activated when using -Wall */ |
#define FD_INVERT 0x0002 /* invert value before storing */ |
typedef struct FlagDef { |
uint16_t offset; |
uint16_t flags; |
const char *name; |
} FlagDef; |
static const FlagDef warning_defs[] = { |
{ offsetof(TCCState, warn_unsupported), 0, "unsupported" }, |
{ offsetof(TCCState, warn_write_strings), 0, "write-strings" }, |
{ offsetof(TCCState, warn_error), 0, "error" }, |
{ offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, |
"implicit-function-declaration" }, |
}; |
ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, |
const char *name, int value) |
{ |
int i; |
const FlagDef *p; |
const char *r; |
r = name; |
if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') { |
r += 3; |
value = !value; |
} |
for(i = 0, p = flags; i < nb_flags; i++, p++) { |
if (!strcmp(r, p->name)) |
goto found; |
} |
return -1; |
found: |
if (p->flags & FD_INVERT) |
value = !value; |
*(int *)((uint8_t *)s + p->offset) = value; |
return 0; |
} |
/* set/reset a warning */ |
static int tcc_set_warning(TCCState *s, const char *warning_name, int value) |
{ |
int i; |
const FlagDef *p; |
if (!strcmp(warning_name, "all")) { |
for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) { |
if (p->flags & WD_ALL) |
*(int *)((uint8_t *)s + p->offset) = 1; |
} |
s->warn_unsupported = 1; // siemargl. was unused flag about compiler features |
return 0; |
} else { |
return set_flag(s, warning_defs, countof(warning_defs), |
warning_name, value); |
} |
} |
static const FlagDef flag_defs[] = { |
{ offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, |
{ offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, |
{ offsetof(TCCState, nocommon), FD_INVERT, "common" }, |
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, |
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" }, |
{ offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" }, |
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, |
{ offsetof(TCCState, normalize_inc_dirs), 0, "normalize-inc-dirs" }, |
}; |
/* set/reset a flag */ |
static int tcc_set_flag(TCCState *s, const char *flag_name, int value) |
{ |
return set_flag(s, flag_defs, countof(flag_defs), |
flag_name, value); |
} |
static int strstart(const char *val, const char **str) |
{ |
const char *p, *q; |
p = *str; |
q = val; |
while (*q) { |
if (*p != *q) |
return 0; |
p++; |
q++; |
} |
*str = p; |
return 1; |
} |
/* Like strstart, but automatically takes into account that ld options can |
* |
* - start with double or single dash (e.g. '--soname' or '-soname') |
* - arguments can be given as separate or after '=' (e.g. '-Wl,-soname,x.so' |
* or '-Wl,-soname=x.so') |
* |
* you provide `val` always in 'option[=]' form (no leading -) |
*/ |
static int link_option(const char *str, const char *val, const char **ptr) |
{ |
const char *p, *q; |
/* there should be 1 or 2 dashes */ |
if (*str++ != '-') |
return 0; |
if (*str == '-') |
str++; |
/* then str & val should match (potentialy up to '=') */ |
p = str; |
q = val; |
while (*q != '\0' && *q != '=') { |
if (*p != *q) |
return 0; |
p++; |
q++; |
} |
/* '=' near eos means ',' or '=' is ok */ |
if (*q == '=') { |
if (*p != ',' && *p != '=') |
return 0; |
p++; |
q++; |
} |
if (ptr) |
*ptr = p; |
return 1; |
} |
static const char *skip_linker_arg(const char **str) |
{ |
const char *s1 = *str; |
const char *s2 = strchr(s1, ','); |
*str = s2 ? s2++ : (s2 = s1 + strlen(s1)); |
return s2; |
} |
static char *copy_linker_arg(const char *p) |
{ |
const char *q = p; |
skip_linker_arg(&q); |
return pstrncpy(tcc_malloc(q - p + 1), p, q - p); |
} |
/* set linker options */ |
static int tcc_set_linker(TCCState *s, const char *option) |
{ |
while (option && *option) { |
const char *p = option; |
char *end = NULL; |
int ignoring = 0; |
if (link_option(option, "Bsymbolic", &p)) { |
s->symbolic = 1; |
} else if (link_option(option, "nostdlib", &p)) { |
s->nostdlib = 1; |
} else if (link_option(option, "fini=", &p)) { |
s->fini_symbol = copy_linker_arg(p); |
ignoring = 1; |
} else if (link_option(option, "image-base=", &p) |
|| link_option(option, "Ttext=", &p)) { |
s->text_addr = strtoull(p, &end, 16); |
s->has_text_addr = 1; |
} else if (link_option(option, "init=", &p)) { |
s->init_symbol = copy_linker_arg(p); |
ignoring = 1; |
} else if (link_option(option, "oformat=", &p)) { |
#if defined(TCC_TARGET_PE) |
if (strstart("pe-", &p)) { |
#elif defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64) |
if (strstart("elf64-", &p)) { |
#else |
if (strstart("elf32-", &p)) { |
#endif |
s->output_format = TCC_OUTPUT_FORMAT_ELF; |
} else if (!strcmp(p, "binary")) { |
s->output_format = TCC_OUTPUT_FORMAT_BINARY; |
#ifdef TCC_TARGET_COFF |
} else if (!strcmp(p, "coff")) { |
s->output_format = TCC_OUTPUT_FORMAT_COFF; |
#endif |
} else |
goto err; |
} else if (link_option(option, "as-needed", &p)) { |
ignoring = 1; |
} else if (link_option(option, "O", &p)) { |
ignoring = 1; |
} else if (link_option(option, "rpath=", &p)) { |
s->rpath = copy_linker_arg(p); |
} else if (link_option(option, "section-alignment=", &p)) { |
s->section_align = strtoul(p, &end, 16); |
} else if (link_option(option, "soname=", &p)) { |
s->soname = copy_linker_arg(p); |
#ifdef TCC_TARGET_PE |
} else if (link_option(option, "file-alignment=", &p)) { |
s->pe_file_align = strtoul(p, &end, 16); |
} else if (link_option(option, "stack=", &p)) { |
s->pe_stack_size = strtoul(p, &end, 10); |
} else if (link_option(option, "subsystem=", &p)) { |
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
if (!strcmp(p, "native")) { |
s->pe_subsystem = 1; |
} else if (!strcmp(p, "console")) { |
s->pe_subsystem = 3; |
} else if (!strcmp(p, "gui")) { |
s->pe_subsystem = 2; |
} else if (!strcmp(p, "posix")) { |
s->pe_subsystem = 7; |
} else if (!strcmp(p, "efiapp")) { |
s->pe_subsystem = 10; |
} else if (!strcmp(p, "efiboot")) { |
s->pe_subsystem = 11; |
} else if (!strcmp(p, "efiruntime")) { |
s->pe_subsystem = 12; |
} else if (!strcmp(p, "efirom")) { |
s->pe_subsystem = 13; |
#elif defined(TCC_TARGET_ARM) |
if (!strcmp(p, "wince")) { |
s->pe_subsystem = 9; |
#endif |
} else |
goto err; |
#endif |
} else |
goto err; |
if (ignoring && s->warn_unsupported) err: { |
char buf[100], *e; |
pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e); |
if (ignoring) |
tcc_warning("unsupported linker option '%s'", buf); |
else |
tcc_error("unsupported linker option '%s'", buf); |
} |
option = skip_linker_arg(&p); |
} |
return 0; |
} |
typedef struct TCCOption { |
const char *name; |
uint16_t index; |
uint16_t flags; |
} TCCOption; |
enum { |
TCC_OPTION_HELP, |
TCC_OPTION_I, |
TCC_OPTION_D, |
TCC_OPTION_U, |
TCC_OPTION_P, |
TCC_OPTION_L, |
TCC_OPTION_B, |
TCC_OPTION_l, |
TCC_OPTION_bench, |
TCC_OPTION_bt, |
TCC_OPTION_b, |
TCC_OPTION_g, |
TCC_OPTION_c, |
TCC_OPTION_C, |
TCC_OPTION_dumpversion, |
TCC_OPTION_d, |
TCC_OPTION_float_abi, |
TCC_OPTION_static, |
TCC_OPTION_std, |
TCC_OPTION_shared, |
TCC_OPTION_soname, |
TCC_OPTION_o, |
TCC_OPTION_r, |
TCC_OPTION_s, |
TCC_OPTION_traditional, |
TCC_OPTION_Wl, |
TCC_OPTION_W, |
TCC_OPTION_O, |
TCC_OPTION_m, |
TCC_OPTION_f, |
TCC_OPTION_isystem, |
TCC_OPTION_iwithprefix, |
TCC_OPTION_nostdinc, |
TCC_OPTION_nostdlib, |
TCC_OPTION_print_search_dirs, |
TCC_OPTION_rdynamic, |
TCC_OPTION_pedantic, |
TCC_OPTION_pthread, |
TCC_OPTION_run, |
TCC_OPTION_v, |
TCC_OPTION_w, |
TCC_OPTION_pipe, |
TCC_OPTION_E, |
TCC_OPTION_MD, |
TCC_OPTION_MF, |
TCC_OPTION_x |
}; |
#define TCC_OPTION_HAS_ARG 0x0001 |
#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */ |
static const TCCOption tcc_options[] = { |
{ "h", TCC_OPTION_HELP, 0 }, |
{ "-help", TCC_OPTION_HELP, 0 }, |
{ "?", TCC_OPTION_HELP, 0 }, |
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, |
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, |
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, |
{ "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG }, |
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG }, |
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "bench", TCC_OPTION_bench, 0 }, |
#ifdef CONFIG_TCC_BACKTRACE |
{ "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG }, |
#endif |
#ifdef CONFIG_TCC_BCHECK |
{ "b", TCC_OPTION_b, 0 }, |
#endif |
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "c", TCC_OPTION_c, 0 }, |
{ "C", TCC_OPTION_C, 0 }, |
{ "dumpversion", TCC_OPTION_dumpversion, 0}, |
{ "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
#ifdef TCC_TARGET_ARM |
{ "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG }, |
#endif |
{ "static", TCC_OPTION_static, 0 }, |
{ "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "shared", TCC_OPTION_shared, 0 }, |
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG }, |
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, |
{ "pedantic", TCC_OPTION_pedantic, 0}, |
{ "pthread", TCC_OPTION_pthread, 0}, |
{ "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "rdynamic", TCC_OPTION_rdynamic, 0 }, |
{ "r", TCC_OPTION_r, 0 }, |
{ "s", TCC_OPTION_s, 0 }, |
{ "traditional", TCC_OPTION_traditional, 0 }, |
{ "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG }, |
{ "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG }, |
{ "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG }, |
{ "nostdinc", TCC_OPTION_nostdinc, 0 }, |
{ "nostdlib", TCC_OPTION_nostdlib, 0 }, |
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, |
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
{ "w", TCC_OPTION_w, 0 }, |
{ "pipe", TCC_OPTION_pipe, 0}, |
{ "E", TCC_OPTION_E, 0}, |
{ "MD", TCC_OPTION_MD, 0}, |
{ "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, |
{ "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, |
{ NULL, 0, 0 }, |
}; |
static void parse_option_D(TCCState *s1, const char *optarg) |
{ |
char *sym = tcc_strdup(optarg); |
char *value = strchr(sym, '='); |
if (value) |
*value++ = '\0'; |
tcc_define_symbol(s1, sym, value); |
tcc_free(sym); |
} |
static void args_parser_add_file(TCCState *s, const char* filename, int filetype) |
{ |
int len = strlen(filename); |
char *p = tcc_malloc(len + 2); |
if (filetype) { |
*p = filetype; |
} |
else { |
/* use a file extension to detect a filetype */ |
const char *ext = tcc_fileextension(filename); |
if (ext[0]) { |
ext++; |
if (!strcmp(ext, "S")) |
*p = TCC_FILETYPE_ASM_PP; |
else |
if (!strcmp(ext, "s")) |
*p = TCC_FILETYPE_ASM; |
else |
if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i")) |
*p = TCC_FILETYPE_C; |
else |
*p = TCC_FILETYPE_BINARY; |
} |
else { |
*p = TCC_FILETYPE_C; |
} |
} |
strcpy(p+1, filename); |
dynarray_add((void ***)&s->files, &s->nb_files, p); |
} |
ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) |
{ |
const TCCOption *popt; |
const char *optarg, *r; |
int optind = 0; |
ParseArgsState *pas = s->parse_args_state; |
while (optind < argc) { |
r = argv[optind++]; |
if (r[0] != '-' || r[1] == '\0') { |
/* handle list files */ |
if (r[0] == '@' && r[1]) { |
char buf[sizeof file->filename], *p; |
char **argv = NULL; |
int argc = 0; |
FILE *fp; |
fp = fopen(r + 1, "rb"); |
if (fp == NULL) |
tcc_error("list file '%s' not found", r + 1); |
while (fgets(buf, sizeof buf, fp)) { |
p = trimfront(trimback(buf, strchr(buf, 0))); |
if (0 == *p || ';' == *p) |
continue; |
dynarray_add((void ***)&argv, &argc, tcc_strdup(p)); |
} |
fclose(fp); |
tcc_parse_args1(s, argc, argv); |
dynarray_reset(&argv, &argc); |
} else { |
args_parser_add_file(s, r, pas->filetype); |
if (pas->run) { |
optind--; |
/* argv[0] will be this file */ |
break; |
} |
} |
continue; |
} |
/* find option in table */ |
for(popt = tcc_options; ; ++popt) { |
const char *p1 = popt->name; |
const char *r1 = r + 1; |
if (p1 == NULL) |
tcc_error("invalid option -- '%s'", r); |
if (!strstart(p1, &r1)) |
continue; |
optarg = r1; |
if (popt->flags & TCC_OPTION_HAS_ARG) { |
if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) { |
if (optind >= argc) |
tcc_error("argument to '%s' is missing", r); |
optarg = argv[optind++]; |
} |
} else if (*r1 != '\0') |
continue; |
break; |
} |
switch(popt->index) { |
case TCC_OPTION_HELP: |
return 0; |
case TCC_OPTION_I: |
tcc_add_include_path(s, optarg); |
break; |
case TCC_OPTION_D: |
parse_option_D(s, optarg); |
break; |
case TCC_OPTION_U: |
tcc_undefine_symbol(s, optarg); |
break; |
case TCC_OPTION_L: |
tcc_add_library_path(s, optarg); |
break; |
case TCC_OPTION_B: |
/* set tcc utilities path (mainly for tcc development) */ |
tcc_set_lib_path(s, optarg); |
break; |
case TCC_OPTION_l: |
args_parser_add_file(s, r, TCC_FILETYPE_BINARY); |
s->nb_libraries++; |
break; |
case TCC_OPTION_pthread: |
parse_option_D(s, "_REENTRANT"); |
pas->pthread = 1; |
break; |
case TCC_OPTION_bench: |
s->do_bench = 1; |
break; |
#ifdef CONFIG_TCC_BACKTRACE |
case TCC_OPTION_bt: |
tcc_set_num_callers(atoi(optarg)); |
break; |
#endif |
#ifdef CONFIG_TCC_BCHECK |
case TCC_OPTION_b: |
s->do_bounds_check = 1; |
s->do_debug = 1; |
break; |
#endif |
case TCC_OPTION_g: |
s->do_debug = 1; |
break; |
case TCC_OPTION_c: |
if (s->output_type) |
tcc_warning("-c: some compiler action already specified (%d)", s->output_type); |
s->output_type = TCC_OUTPUT_OBJ; |
break; |
case TCC_OPTION_C: |
s->option_C = 1; |
break; |
case TCC_OPTION_d: |
if (*optarg == 'D' || *optarg == 'M') |
s->dflag = *optarg; |
else { |
if (s->warn_unsupported) |
goto unsupported_option; |
tcc_error("invalid option -- '%s'", r); |
} |
break; |
#ifdef TCC_TARGET_ARM |
case TCC_OPTION_float_abi: |
/* tcc doesn't support soft float yet */ |
if (!strcmp(optarg, "softfp")) { |
s->float_abi = ARM_SOFTFP_FLOAT; |
tcc_undefine_symbol(s, "__ARM_PCS_VFP"); |
} else if (!strcmp(optarg, "hard")) |
s->float_abi = ARM_HARD_FLOAT; |
else |
tcc_error("unsupported float abi '%s'", optarg); |
break; |
#endif |
case TCC_OPTION_static: |
s->static_link = 1; |
break; |
case TCC_OPTION_std: |
/* silently ignore, a current purpose: |
allow to use a tcc as a reference compiler for "make test" */ |
break; |
case TCC_OPTION_shared: |
if (s->output_type) |
tcc_warning("-shared: some compiler action already specified (%d)", s->output_type); |
s->output_type = TCC_OUTPUT_DLL; |
break; |
case TCC_OPTION_soname: |
s->soname = tcc_strdup(optarg); |
break; |
case TCC_OPTION_m: |
s->option_m = tcc_strdup(optarg); |
break; |
case TCC_OPTION_o: |
if (s->outfile) { |
tcc_warning("multiple -o option"); |
tcc_free(s->outfile); |
} |
s->outfile = tcc_strdup(optarg); |
break; |
case TCC_OPTION_r: |
/* generate a .o merging several output files */ |
if (s->output_type) |
tcc_warning("-r: some compiler action already specified (%d)", s->output_type); |
s->option_r = 1; |
s->output_type = TCC_OUTPUT_OBJ; |
break; |
case TCC_OPTION_isystem: |
tcc_add_sysinclude_path(s, optarg); |
break; |
case TCC_OPTION_iwithprefix: |
if (1) { |
char buf[1024]; |
int buf_size = sizeof(buf)-1; |
char *p = &buf[0]; |
char *sysroot = "{B}/"; |
int len = strlen(sysroot); |
if (len > buf_size) |
len = buf_size; |
strncpy(p, sysroot, len); |
p += len; |
buf_size -= len; |
len = strlen(optarg); |
if (len > buf_size) |
len = buf_size; |
strncpy(p, optarg, len+1); |
tcc_add_sysinclude_path(s, buf); |
} |
break; |
case TCC_OPTION_nostdinc: |
s->nostdinc = 1; |
break; |
case TCC_OPTION_nostdlib: |
s->nostdlib = 1; |
break; |
case TCC_OPTION_print_search_dirs: |
s->print_search_dirs = 1; |
break; |
case TCC_OPTION_run: |
if (s->output_type) |
tcc_warning("-run: some compiler action already specified (%d)", s->output_type); |
s->output_type = TCC_OUTPUT_MEMORY; |
tcc_set_options(s, optarg); |
pas->run = 1; |
break; |
case TCC_OPTION_v: |
do ++s->verbose; while (*optarg++ == 'v'); |
break; |
case TCC_OPTION_f: |
if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported) |
goto unsupported_option; |
break; |
case TCC_OPTION_W: |
if (tcc_set_warning(s, optarg, 1) < 0 && |
s->warn_unsupported) |
goto unsupported_option; |
break; |
case TCC_OPTION_w: |
s->warn_none = 1; |
break; |
case TCC_OPTION_rdynamic: |
s->rdynamic = 1; |
break; |
case TCC_OPTION_Wl: |
if (pas->linker_arg.size) |
--pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ','); |
cstr_cat(&pas->linker_arg, optarg, 0); |
break; |
case TCC_OPTION_E: |
if (s->output_type) |
tcc_warning("-E: some compiler action already specified (%d)", s->output_type); |
s->output_type = TCC_OUTPUT_PREPROCESS; |
break; |
case TCC_OPTION_P: |
s->Pflag = atoi(optarg) + 1; |
break; |
case TCC_OPTION_MD: |
s->gen_deps = 1; |
break; |
case TCC_OPTION_MF: |
s->deps_outfile = tcc_strdup(optarg); |
break; |
case TCC_OPTION_dumpversion: |
printf ("%s\n", TCC_VERSION); |
exit(0); |
case TCC_OPTION_s: |
s->do_strip = 1; |
break; |
case TCC_OPTION_traditional: |
break; |
case TCC_OPTION_x: |
if (*optarg == 'c') |
pas->filetype = TCC_FILETYPE_C; |
else |
if (*optarg == 'a') |
pas->filetype = TCC_FILETYPE_ASM_PP; |
else |
if (*optarg == 'n') |
pas->filetype = 0; |
else |
tcc_warning("unsupported language '%s'", optarg); |
break; |
case TCC_OPTION_O: |
if (1) { |
int opt = atoi(optarg); |
char *sym = "__OPTIMIZE__"; |
if (opt) |
tcc_define_symbol(s, sym, 0); |
else |
tcc_undefine_symbol(s, sym); |
} |
break; |
case TCC_OPTION_pedantic: |
case TCC_OPTION_pipe: |
/* ignored */ |
break; |
default: |
if (s->warn_unsupported) { |
unsupported_option: |
tcc_warning("unsupported option '%s'", r); |
} |
break; |
} |
} |
return optind; |
} |
PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) |
{ |
ParseArgsState *pas; |
int ret, is_allocated = 0; |
if (!s->parse_args_state) { |
s->parse_args_state = tcc_mallocz(sizeof(ParseArgsState)); |
cstr_new(&s->parse_args_state->linker_arg); |
is_allocated = 1; |
} |
pas = s->parse_args_state; |
ret = tcc_parse_args1(s, argc, argv); |
if (s->output_type == 0) |
s->output_type = TCC_OUTPUT_EXE; |
if (pas->pthread && s->output_type != TCC_OUTPUT_OBJ) |
tcc_set_options(s, "-lpthread"); |
if (s->output_type == TCC_OUTPUT_EXE) |
tcc_set_linker(s, (const char *)pas->linker_arg.data); |
if (is_allocated) { |
cstr_free(&pas->linker_arg); |
tcc_free(pas); |
s->parse_args_state = NULL; |
} |
return ret; |
} |
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) |
{ |
const char *s1; |
char **argv, *arg; |
int argc, len; |
int ret; |
argc = 0, argv = NULL; |
for(;;) { |
while (is_space(*str)) |
str++; |
if (*str == '\0') |
break; |
s1 = str; |
while (*str != '\0' && !is_space(*str)) |
str++; |
len = str - s1; |
arg = tcc_malloc(len + 1); |
pstrncpy(arg, s1, len); |
dynarray_add((void ***)&argv, &argc, arg); |
} |
ret = tcc_parse_args(s, argc, argv); |
dynarray_reset(&argv, &argc); |
return ret; |
} |
PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time) |
{ |
double tt; |
tt = (double)total_time / 1000000.0; |
if (tt < 0.001) |
tt = 0.001; |
if (total_bytes < 1) |
total_bytes = 1; |
fprintf(stderr, "%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", |
tok_ident - TOK_IDENT, total_lines, total_bytes, |
tt, (int)(total_lines / tt), |
total_bytes / tt / 1000000.0); |
} |
PUB_FUNC void tcc_set_environment(TCCState *s) |
{ |
char * path; |
path = getenv("C_INCLUDE_PATH"); |
if(path != NULL) { |
tcc_add_include_path(s, path); |
} |
path = getenv("CPATH"); |
if(path != NULL) { |
tcc_add_include_path(s, path); |
} |
path = getenv("LIBRARY_PATH"); |
if(path != NULL) { |
tcc_add_library_path(s, path); |
} |
} |
/programs/develop/ktcc/trunk/source/libtcc.h |
---|
1,6 → 1,10 |
#ifndef LIBTCC_H |
#define LIBTCC_H |
#ifndef LIBTCCAPI |
# define LIBTCCAPI |
#endif |
#ifdef __cplusplus |
extern "C" { |
#endif |
10,85 → 14,88 |
typedef struct TCCState TCCState; |
/* create a new TCC compilation context */ |
TCCState *tcc_new(void); |
LIBTCCAPI TCCState *tcc_new(void); |
/* free a TCC compilation context */ |
void tcc_delete(TCCState *s); |
LIBTCCAPI void tcc_delete(TCCState *s); |
/* add debug information in the generated code */ |
void tcc_enable_debug(TCCState *s); |
/* set CONFIG_TCCDIR at runtime */ |
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); |
/* set error/warning display callback */ |
void tcc_set_error_func(TCCState *s, void *error_opaque, |
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, |
void (*error_func)(void *opaque, const char *msg)); |
/* set/reset a warning */ |
int tcc_set_warning(TCCState *s, const char *warning_name, int value); |
/* set options as from command line (multiple supported) */ |
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str); |
/*****************************/ |
/* preprocessor */ |
/* add include path */ |
int tcc_add_include_path(TCCState *s, const char *pathname); |
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname); |
/* add in system include path */ |
int tcc_add_sysinclude_path(TCCState *s, const char *pathname); |
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname); |
/* define preprocessor symbol 'sym'. Can put optional value */ |
void tcc_define_symbol(TCCState *s, const char *sym, const char *value); |
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value); |
/* undefine preprocess symbol 'sym' */ |
void tcc_undefine_symbol(TCCState *s, const char *sym); |
LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym); |
/*****************************/ |
/* compiling */ |
/* add a file (either a C file, dll, an object, a library or an ld |
script). Return -1 if error. */ |
int tcc_add_file(TCCState *s, const char *filename); |
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */ |
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename, int filetype); |
#define TCC_FILETYPE_BINARY 1 |
#define TCC_FILETYPE_C 2 |
#define TCC_FILETYPE_ASM 3 |
#define TCC_FILETYPE_ASM_PP 4 |
/* compile a string containing a C source. Return non zero if |
error. */ |
int tcc_compile_string(TCCState *s, const char *buf); |
/* compile a string containing a C source. Return -1 if error. */ |
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); |
/*****************************/ |
/* linking commands */ |
/* set output type. MUST BE CALLED before any compilation */ |
#define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no |
output file) (default) */ |
#define TCC_OUTPUT_EXE 1 /* executable file */ |
#define TCC_OUTPUT_DLL 2 /* dynamic library */ |
#define TCC_OUTPUT_OBJ 3 /* object file */ |
int tcc_set_output_type(TCCState *s, int output_type); |
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type); |
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */ |
#define TCC_OUTPUT_EXE 2 /* executable file */ |
#define TCC_OUTPUT_DLL 3 /* dynamic library */ |
#define TCC_OUTPUT_OBJ 4 /* object file */ |
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */ |
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */ |
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */ |
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */ |
/* equivalent to -Lpath option */ |
int tcc_add_library_path(TCCState *s, const char *pathname); |
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname); |
/* the library name is the same as the argument of the '-l' option */ |
int tcc_add_library(TCCState *s, const char *libraryname); |
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname); |
/* add a symbol to the compiled program */ |
int tcc_add_symbol(TCCState *s, const char *name, unsigned long val); |
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val); |
/* output an executable, library or object file. DO NOT call |
tcc_relocate() before. */ |
int tcc_output_file(TCCState *s, const char *filename); |
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename); |
/* link and run main() function and return its value. DO NOT call |
tcc_relocate() before. */ |
int tcc_run(TCCState *s, int argc, char **argv); |
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv); |
/* do all relocations (needed before using tcc_get_symbol()). Return |
non zero if link error. */ |
int tcc_relocate(TCCState *s); |
/* do all relocations (needed before using tcc_get_symbol()) */ |
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr); |
/* possible values for 'ptr': |
- TCC_RELOCATE_AUTO : Allocate and manage memory internally |
- NULL : return required memory size for the step below |
- memory address : copy code to memory passed by the caller |
returns -1 if error. */ |
#define TCC_RELOCATE_AUTO (void*)1 |
/* return symbol value. return 0 if OK, -1 if symbol not found */ |
int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name); |
/* return symbol value or NULL if not found */ |
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); |
#ifdef __cplusplus |
} |
/programs/develop/ktcc/trunk/source/readme_kos32.txt |
---|
0,0 → 1,89 |
Siemargl port comments |
Used github branch https://github.com/TinyCC/tinycc |
It have a vesion 0.9.26 with heads up to 0.9.27 - see ChangeLog |
Kolibri version errata/changelog: |
-added TCC_TARGET_MEOS as needed |
-leading_underscore by default is 0 (can use -f[no-]leading-underscore), |
otherwise (error) underscoring all symbols, not only cdecl |
-added message in tccmeos.c about missed symbols when linking KOS executable |
-start.o added automatically, when -nostdlib not used |
-to use standard ktcc lib must add -lck at commandline |
-default search paths are ./include ./lib from executable (under KOS need to |
use -Bpath_to_ktcc and put start.o in current dir) |
-when config.h is ready, compiler can be easy builded as [kos32-]gcc tcc.c libtcc.c |
see also makefile.kos32 |
-silent (kos) -> writes to debugboard |
-impossible using with mingw-gcc compiled lib, incompatible library format: |
.o is PE-format from gcc but ELF from tcc, may be linux-gcc does it ok |
-no symbols (mapfile) for debug, see howtodebugtcc |
-how to use packed attribute see test82 |
-alias attribute wont work |
-unnamed structs in union may lead to compiler internal error |
-tcc: error: undefined symbol '__tcc_cvt_ftol' |
--in config.h - used workaround (#define COMMIT_4ad186c5ef61_IS_FIXED |
--but this is precision bugfix - see \tests\tests2\000_cvttoftol.c |
-not working: default search path are ./include ./lib from executable |
--under KOS need to use -Bpath_to_ktcc |
--start.o not found using -B (kos) - put near your.c file |
-if static var sized more than 14096+ -> crash compiled .exe (kos) |
---^ stack size set in menuet header at compile time tccmeos.c:177 about 4k |
Tests status: |
asmtest + |
abitest not tested (embedding compiler) |
libtcctest not tested (embedding compiler) |
boundtest ----- alloca removed from tcc libtcc.c:945 (really not worked) |
tcctest most test ok, some problems with long double |
vla_test.c + |
pp/* + (minor comment error in 13.s) |
tests2/* : see below |
// errata |
skippin' tests |
test76 fail dollars in identifiers |
test34 fail (array assignment not supported) |
test73 fail compile (no stdint.h), printfloat, ARM specific |
test46 no stdin - removed funtionality read from console, but file ops works |
libc: |
-no "finished" in title of console program after exit console - use con_exit() |
-bench timing error (0s or 1s) |
-minimal memory allocator |
-memmove cannot overlap |
libc not full |
no files: |
assert.h |
errno.h |
limits.h |
locale.h |
setjmp.h |
signall.h |
time.h |
check functions: |
stdio.h: |
Operations on files: none http://www.cplusplus.com/reference/cstdio/ |
reopen |
setbuf, setvbuf |
scanf, sscanf, vfscanf(C11), vscanf(C11), vsscanf(C11) |
vfprintf, vsfprintf |
+fgets, gets |
fputs, puts |
getchar |
putc |
+putchar |
Error-handling: only feof |
Macros: only EOF, NULL, FILE |
-all files in libc/kolibrisys catalog are stdcall in header, but in asm cdecl |
/programs/develop/ktcc/trunk/source/tcc-doc.info |
---|
0,0 → 1,1227 |
This is tcc-doc.info, produced by makeinfo version 4.13 from |
D:\VSProjects\msys-kos32-4.8.2\ktcc\branch-0.9.27\source\tcc-doc.texi. |
INFO-DIR-SECTION Software development |
START-INFO-DIR-ENTRY |
* TCC: (tcc-doc). The Tiny C Compiler. |
END-INFO-DIR-ENTRY |
File: tcc-doc.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) |
Tiny C Compiler Reference Documentation |
*************************************** |
This manual documents version 0.9.26 of the Tiny C Compiler. |
* Menu: |
* Introduction:: Introduction to tcc. |
* Invoke:: Invocation of tcc (command line, options). |
* Clang:: ANSI C and extensions. |
* asm:: Assembler syntax. |
* linker:: Output file generation and supported targets. |
* Bounds:: Automatic bounds-checking of C code. |
* Libtcc:: The libtcc library. |
* devel:: Guide for Developers. |
File: tcc-doc.info, Node: Introduction, Next: Invoke, Prev: Top, Up: Top |
1 Introduction |
************** |
TinyCC (aka TCC) is a small but hyper fast C compiler. Unlike other C |
compilers, it is meant to be self-relying: you do not need an external |
assembler or linker because TCC does that for you. |
TCC compiles so _fast_ that even for big projects `Makefile's may |
not be necessary. |
TCC not only supports ANSI C, but also most of the new ISO C99 |
standard and many GNUC extensions including inline assembly. |
TCC can also be used to make _C scripts_, i.e. pieces of C source |
that you run as a Perl or Python script. Compilation is so fast that |
your script will be as fast as if it was an executable. |
TCC can also automatically generate memory and bound checks (*note |
Bounds::) while allowing all C pointers operations. TCC can do these |
checks even if non patched libraries are used. |
With `libtcc', you can use TCC as a backend for dynamic code |
generation (*note Libtcc::). |
TCC mainly supports the i386 target on Linux and Windows. There are |
alpha ports for the ARM (`arm-tcc') and the TMS320C67xx targets |
(`c67-tcc'). More information about the ARM port is available at |
`http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html'. |
For usage on Windows, see also `tcc-win32.txt'. |
File: tcc-doc.info, Node: Invoke, Next: Clang, Prev: Introduction, Up: Top |
2 Command line invocation |
************************* |
2.1 Quick start |
=============== |
usage: tcc [options] [INFILE1 INFILE2...] [`-run' INFILE ARGS...] |
TCC options are a very much like gcc options. The main difference is |
that TCC can also execute directly the resulting program and give it |
runtime arguments. |
Here are some examples to understand the logic: |
``tcc -run a.c'' |
Compile `a.c' and execute it directly |
``tcc -run a.c arg1'' |
Compile a.c and execute it directly. arg1 is given as first |
argument to the `main()' of a.c. |
``tcc a.c -run b.c arg1'' |
Compile `a.c' and `b.c', link them together and execute them. arg1 |
is given as first argument to the `main()' of the resulting |
program. |
``tcc -o myprog a.c b.c'' |
Compile `a.c' and `b.c', link them and generate the executable |
`myprog'. |
``tcc -o myprog a.o b.o'' |
link `a.o' and `b.o' together and generate the executable `myprog'. |
``tcc -c a.c'' |
Compile `a.c' and generate object file `a.o'. |
``tcc -c asmfile.S'' |
Preprocess with C preprocess and assemble `asmfile.S' and generate |
object file `asmfile.o'. |
``tcc -c asmfile.s'' |
Assemble (but not preprocess) `asmfile.s' and generate object file |
`asmfile.o'. |
``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'. |
Scripting: |
TCC can be invoked from _scripts_, just as shell scripts. You just |
need to add `#!/usr/local/bin/tcc -run' at the start of your C source: |
#!/usr/local/bin/tcc -run |
#include <stdio.h> |
int main() |
{ |
printf("Hello World\n"); |
return 0; |
} |
TCC can read C source code from _standard input_ when `-' is used in |
place of `infile'. Example: |
echo 'main(){puts("hello");}' | tcc -run - |
2.2 Option summary |
================== |
General Options: |
`-c' |
Generate an object file. |
`-o outfile' |
Put object file, executable, or dll into output file `outfile'. |
`-run source [args...]' |
Compile file SOURCE and run it with the command line arguments |
ARGS. In order to be able to give more than one argument to a |
script, several TCC options can be given _after_ the `-run' |
option, separated by spaces: |
tcc "-run -L/usr/X11R6/lib -lX11" ex4.c |
In a script, it gives the following header: |
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 |
`-mfloat-abi (ARM only)' |
Select the float ABI. Possible values: `softfp' and `hard' |
`-dumpversion' |
Print only the compiler version and nothing else. |
`-v' |
Display TCC version. |
`-vv' |
Show included files. As sole argument, print search dirs (as |
below). |
`-bench' |
Display compilation statistics. |
`-print-search-dirs' |
Print the configured installation directory and a list of library |
and include directories tcc will search. |
Preprocessor options: |
`-Idir' |
Specify an additional include path. Include paths are searched in |
the order they are specified. |
System include paths are always searched after. The default system |
include paths are: `/usr/local/include', `/usr/include' and |
`PREFIX/lib/tcc/include'. (`PREFIX' is usually `/usr' or |
`/usr/local'). |
`-Dsym[=val]' |
Define preprocessor symbol `sym' to val. If val is not present, |
its value is `1'. Function-like macros can also be defined: |
`-DF(a)=a+1' |
`-Usym' |
Undefine preprocessor symbol `sym'. |
Compilation flags: |
Note: each of the following options has a negative form beginning |
with `-fno-'. |
`-funsigned-char' |
Let the `char' type be unsigned. |
`-fsigned-char' |
Let the `char' type be signed. |
`-fno-common' |
Do not generate common symbols for uninitialized data. |
`-fleading-underscore' |
Add a leading underscore at the beginning of each C symbol. |
`-fms-extensions' |
Allow a MS C compiler extensions to the language. Curretly this |
assume a nested named structure declaration without identifier |
behave like an unnamed one. |
`-fdollars-in-identifiers' |
Allow a dollars in identifiers. |
`-fnormalize-inc-dirs' |
Be more gcc compatible and remove non-existent or duplicate |
directories from include paths. This helps to compile such |
packages as coreutils. |
Warning options: |
`-w' |
Disable all warnings. |
Note: each of the following warning options has a negative form |
beginning with `-Wno-'. |
`-Wimplicit-function-declaration' |
Warn about implicit function declaration. |
`-Wunsupported' |
Warn about unsupported GCC features that are ignored by TCC. |
`-Wwrite-strings' |
Make string constants be of type `const char *' instead of `char |
*'. |
`-Werror' |
Abort compilation if warnings are issued. |
`-Wall' |
Activate all warnings, except `-Werror', `-Wunusupported' and |
`-Wwrite-strings'. |
Linker options: |
`-Ldir' |
Specify an additional static library path for the `-l' option. The |
default library paths are `/usr/local/lib', `/usr/lib' and `/lib'. |
`-lxxx' |
Link your program with dynamic library libxxx.so or static library |
libxxx.a. The library is searched in the paths specified by the |
`-L' option and `LIBRARY_PATH' variable. |
`-Bdir' |
Set the path where the tcc internal libraries (and include files) |
can be found (default is `PREFIX/lib/tcc'). |
`-shared' |
Generate a shared library instead of an executable. |
`-soname name' |
set name for shared library to be used at runtime |
`-static' |
Generate a statically linked executable (default is a shared linked |
executable). |
`-rdynamic' |
Export global symbols to the dynamic linker. It is useful when a |
library opened with `dlopen()' needs to access executable symbols. |
`-r' |
Generate an object file combining all input files. |
`-Wl,-rpath=path' |
Put custom seatch path for dynamic libraries into executable. |
`-Wl,--oformat=fmt' |
Use FMT as output format. The supported output formats are: |
`elf32-i386' |
ELF output format (default) |
`binary' |
Binary image (only for executable output) |
`coff' |
COFF output format (only for executable output for |
TMS320C67xx target) |
`-Wl,-subsystem=console/gui/wince/...' |
Set type for PE (Windows) executables. |
`-Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]' |
Modify executable layout. |
`-Wl,-Bsymbolic' |
Set DT_SYMBOLIC tag. |
Debugger options: |
`-g' |
Generate run time debug information so that you get clear run time |
error messages: ` test.c:68: in function 'test5()': dereferencing |
invalid pointer' instead of the laconic `Segmentation fault'. |
`-b' |
Generate additional support code to check memory allocations and |
array/pointer bounds. `-g' is implied. Note that the generated |
code is slower and bigger in this case. |
Note: `-b' is only available on i386 when using libtcc for the |
moment. |
`-bt N' |
Display N callers in stack traces. This is useful with `-g' or |
`-b'. |
Misc options: |
`-MD' |
Generate makefile fragment with dependencies. |
`-MF depfile' |
Use `depfile' as output for -MD. |
Note: GCC options `-Ox', `-fx' and `-mx' are ignored. |
Environment variables that affect how tcc operates. |
`CPATH' |
`C_INCLUDE_PATH' |
A colon-separated list of directories searched for include files, |
directories given with `-I' are searched first. |
`LIBRARY_PATH' |
A colon-separated list of directories searched for libraries for |
the `-l' option, directories given with `-L' are searched first. |
File: tcc-doc.info, Node: Clang, Next: asm, Prev: Invoke, Up: Top |
3 C language support |
******************** |
3.1 ANSI C |
========== |
TCC implements all the ANSI C standard, including structure bit fields |
and floating point numbers (`long double', `double', and `float' fully |
supported). |
3.2 ISOC99 extensions |
===================== |
TCC implements many features of the new C standard: ISO C99. Currently |
missing items are: complex and imaginary numbers. |
Currently implemented ISOC99 features: |
* variable length arrays. |
* 64 bit `long long' types are fully supported. |
* The boolean type `_Bool' is supported. |
* `__func__' is a string variable containing the current function |
name. |
* Variadic macros: `__VA_ARGS__' can be used for function-like |
macros: |
#define dprintf(level, __VA_ARGS__) printf(__VA_ARGS__) |
`dprintf' can then be used with a variable number of parameters. |
* Declarations can appear anywhere in a block (as in C++). |
* Array and struct/union elements can be initialized in any order by |
using designators: |
struct { int x, y; } st[10] = { [0].x = 1, [0].y = 2 }; |
int tab[10] = { 1, 2, [5] = 5, [9] = 9}; |
* Compound initializers are supported: |
int *p = (int []){ 1, 2, 3 }; |
to initialize a pointer pointing to an initialized array. The same |
works for structures and strings. |
* Hexadecimal floating point constants are supported: |
double d = 0x1234p10; |
is the same as writing |
double d = 4771840.0; |
* `inline' keyword is ignored. |
* `restrict' keyword is ignored. |
3.3 GNU C extensions |
==================== |
TCC implements some GNU C extensions: |
* array designators can be used without '=': |
int a[10] = { [0] 1, [5] 2, 3, 4 }; |
* Structure field designators can be a label: |
struct { int x, y; } st = { x: 1, y: 1}; |
instead of |
struct { int x, y; } st = { .x = 1, .y = 1}; |
* `\e' is ASCII character 27. |
* case ranges : ranges can be used in `case's: |
switch(a) { |
case 1 ... 9: |
printf("range 1 to 9\n"); |
break; |
default: |
printf("unexpected\n"); |
break; |
} |
* The keyword `__attribute__' is handled to specify variable or |
function attributes. The following attributes are supported: |
* `aligned(n)': align a variable or a structure field to n bytes |
(must be a power of two). |
* `packed': force alignment of a variable or a structure field |
to 1. |
* `section(name)': generate function or data in assembly section |
name (name is a string containing the section name) instead |
of the default section. |
* `unused': specify that the variable or the function is unused. |
* `cdecl': use standard C calling convention (default). |
* `stdcall': use Pascal-like calling convention. |
* `regparm(n)': use fast i386 calling convention. N must be |
between 1 and 3. The first N function parameters are |
respectively put in registers `%eax', `%edx' and `%ecx'. |
* `dllexport': export function from dll/executable (win32 only) |
Here are some examples: |
int a __attribute__ ((aligned(8), section(".mysection"))); |
align variable `a' to 8 bytes and put it in section `.mysection'. |
int my_add(int a, int b) __attribute__ ((section(".mycodesection"))) |
{ |
return a + b; |
} |
generate function `my_add' in section `.mycodesection'. |
* GNU style variadic macros: |
#define dprintf(fmt, args...) printf(fmt, ## args) |
dprintf("no arg\n"); |
dprintf("one arg %d\n", 1); |
* `__FUNCTION__' is interpreted as C99 `__func__' (so it has not |
exactly the same semantics as string literal GNUC where it is a |
string literal). |
* The `__alignof__' keyword can be used as `sizeof' to get the |
alignment of a type or an expression. |
* The `typeof(x)' returns the type of `x'. `x' is an expression or |
a type. |
* Computed gotos: `&&label' returns a pointer of type `void *' on |
the goto label `label'. `goto *expr' can be used to jump on the |
pointer resulting from `expr'. |
* Inline assembly with asm instruction: |
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); |
} |
TCC includes its own x86 inline assembler with a `gas'-like (GNU |
assembler) syntax. No intermediate files are generated. GCC 3.x |
named operands are supported. |
* `__builtin_types_compatible_p()' and `__builtin_constant_p()' are |
supported. |
* `#pragma pack' is supported for win32 compatibility. |
3.4 TinyCC extensions |
===================== |
* `__TINYC__' is a predefined macro to indicate that you use TCC. |
* `#!' at the start of a line is ignored to allow scripting. |
* Binary digits can be entered (`0b101' instead of `5'). |
* `__BOUNDS_CHECKING_ON' is defined if bound checking is activated. |
File: tcc-doc.info, Node: asm, Next: linker, Prev: Clang, Up: Top |
4 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 `.S' (C preprocessed |
assembler) and `.s' extensions. It is also used to handle the GNU |
inline assembler with the `asm' keyword. |
4.1 Syntax |
========== |
TinyCC Assembler supports most of the gas syntax. The tokens are the |
same as C. |
* C and C++ comments are supported. |
* Identifiers are the same as C, so you cannot use '.' or '$'. |
* Only 32 bit integer numbers are supported. |
4.2 Expressions |
=============== |
* Integers in decimal, octal and hexa are supported. |
* Unary operators: +, -, ~. |
* Binary operators in decreasing priority order: |
1. *, /, % |
2. &, |, ^ |
3. +, - |
* 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. |
4.3 Labels |
========== |
* All labels are considered as local, except undefined ones. |
* Numeric labels can be used as local `gas'-like labels. They can |
be defined several times in the same source. Use 'b' (backward) or |
'f' (forward) as suffix to reference them: |
1: |
jmp 1b /* jump to '1' label before */ |
jmp 1f /* jump to '1' label after */ |
1: |
4.4 Directives |
============== |
All directives are preceded by a '.'. The following directives are |
supported: |
* .align n[,value] |
* .skip n[,value] |
* .space n[,value] |
* .byte value1[,...] |
* .word value1[,...] |
* .short value1[,...] |
* .int value1[,...] |
* .long value1[,...] |
* .quad immediate_value1[,...] |
* .globl symbol |
* .global symbol |
* .section section |
* .text |
* .data |
* .bss |
* .fill repeat[,size[,value]] |
* .org n |
* .previous |
* .string string[,...] |
* .asciz string[,...] |
* .ascii string[,...] |
4.5 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. |
File: tcc-doc.info, Node: linker, Next: Bounds, Prev: asm, Up: Top |
5 TinyCC Linker |
*************** |
5.1 ELF file generation |
======================= |
TCC can directly output relocatable ELF files (object files), |
executable ELF files and dynamic ELF libraries without relying on an |
external linker. |
Dynamic ELF libraries can be output but the C compiler does not |
generate position independent code (PIC). It means that the dynamic |
library code generated by TCC cannot be factorized among processes yet. |
TCC linker eliminates unreferenced object code in libraries. A |
single pass is done on the object and library list, so the order in |
which object files and libraries are specified is important (same |
constraint as GNU ld). No grouping options (`--start-group' and |
`--end-group') are supported. |
5.2 ELF file loader |
=================== |
TCC can load ELF object files, archives (.a files) and dynamic |
libraries (.so). |
5.3 PE-i386 file generation |
=========================== |
TCC for Windows supports the native Win32 executable file format |
(PE-i386). It generates EXE files (console and gui) and DLL files. |
For usage on Windows, see also tcc-win32.txt. |
5.4 GNU Linker Scripts |
====================== |
Because on many Linux systems some dynamic libraries (such as |
`/usr/lib/libc.so') are in fact GNU ld link scripts (horrible!), the |
TCC linker also supports a subset of GNU ld scripts. |
The `GROUP' and `FILE' commands are supported. `OUTPUT_FORMAT' and |
`TARGET' are ignored. |
Example from `/usr/lib/libc.so': |
/* GNU ld script |
Use the shared library, but some functions are only in |
the static library, so try that secondarily. */ |
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a ) |
File: tcc-doc.info, Node: Bounds, Next: Libtcc, Prev: linker, Up: Top |
6 TinyCC Memory and Bound checks |
******************************** |
This feature is activated with the `-b' (*note Invoke::). |
Note that pointer size is _unchanged_ and that code generated with |
bound checks is _fully compatible_ with unchecked code. When a pointer |
comes from unchecked code, it is assumed to be valid. Even very obscure |
C code with casts should work correctly. |
For more information about the ideas behind this method, see |
`http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html'. |
Here are some examples of caught errors: |
Invalid range with standard string function: |
{ |
char tab[10]; |
memset(tab, 0, 11); |
} |
Out of bounds-error in global or local arrays: |
{ |
int tab[10]; |
for(i=0;i<11;i++) { |
sum += tab[i]; |
} |
} |
Out of bounds-error in malloc'ed data: |
{ |
int *tab; |
tab = malloc(20 * sizeof(int)); |
for(i=0;i<21;i++) { |
sum += tab4[i]; |
} |
free(tab); |
} |
Access of freed memory: |
{ |
int *tab; |
tab = malloc(20 * sizeof(int)); |
free(tab); |
for(i=0;i<20;i++) { |
sum += tab4[i]; |
} |
} |
Double free: |
{ |
int *tab; |
tab = malloc(20 * sizeof(int)); |
free(tab); |
free(tab); |
} |
File: tcc-doc.info, Node: Libtcc, Next: devel, Prev: Bounds, Up: Top |
7 The `libtcc' library |
********************** |
The `libtcc' library enables you to use TCC as a backend for dynamic |
code generation. |
Read the `libtcc.h' to have an overview of the API. Read |
`libtcc_test.c' to have a very simple example. |
The idea consists in giving a C string containing the program you |
want to compile directly to `libtcc'. Then you can access to any global |
symbol (function or variable) defined. |
File: tcc-doc.info, Node: devel, Prev: Libtcc, Up: Top |
8 Developer's guide |
******************* |
This chapter gives some hints to understand how TCC works. You can skip |
it if you do not intend to modify the TCC code. |
8.1 File reading |
================ |
The `BufferedFile' structure contains the context needed to read a |
file, including the current line number. `tcc_open()' opens a new file |
and `tcc_close()' closes it. `inp()' returns the next character. |
8.2 Lexer |
========= |
`next()' reads the next token in the current file. `next_nomacro()' |
reads the next token without macro expansion. |
`tok' contains the current token (see `TOK_xxx') constants. |
Identifiers and keywords are also keywords. `tokc' contains additional |
infos about the token (for example a constant value if number or string |
token). |
8.3 Parser |
========== |
The parser is hardcoded (yacc is not necessary). It does only one pass, |
except: |
* For initialized arrays with unknown size, a first pass is done to |
count the number of elements. |
* For architectures where arguments are evaluated in reverse order, |
a first pass is done to reverse the argument order. |
8.4 Types |
========= |
The types are stored in a single 'int' variable. It was chosen in the |
first stages of development when tcc was much simpler. Now, it may not |
be the best solution. |
#define VT_INT 0 /* integer type */ |
#define VT_BYTE 1 /* signed byte type */ |
#define VT_SHORT 2 /* short type */ |
#define VT_VOID 3 /* void type */ |
#define VT_PTR 4 /* pointer */ |
#define VT_ENUM 5 /* enum definition */ |
#define VT_FUNC 6 /* function type */ |
#define VT_STRUCT 7 /* struct/union definition */ |
#define VT_FLOAT 8 /* IEEE float */ |
#define VT_DOUBLE 9 /* IEEE double */ |
#define VT_LDOUBLE 10 /* IEEE long double */ |
#define VT_BOOL 11 /* ISOC99 boolean type */ |
#define VT_LLONG 12 /* 64 bit integer */ |
#define VT_LONG 13 /* long integer (NEVER USED as type, only |
during parsing) */ |
#define VT_BTYPE 0x000f /* mask for basic type */ |
#define VT_UNSIGNED 0x0010 /* unsigned type */ |
#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ |
#define VT_VLA 0x20000 /* VLA type (also has VT_PTR and VT_ARRAY) */ |
#define VT_BITFIELD 0x0040 /* bitfield modifier */ |
#define VT_CONSTANT 0x0800 /* const modifier */ |
#define VT_VOLATILE 0x1000 /* volatile modifier */ |
#define VT_DEFSIGN 0x2000 /* signed type */ |
#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */ |
When a reference to another type is needed (for pointers, functions |
and structures), the `32 - VT_STRUCT_SHIFT' high order bits are used to |
store an identifier reference. |
The `VT_UNSIGNED' flag can be set for chars, shorts, ints and long |
longs. |
Arrays are considered as pointers `VT_PTR' with the flag `VT_ARRAY' |
set. Variable length arrays are considered as special arrays and have |
flag `VT_VLA' set instead of `VT_ARRAY'. |
The `VT_BITFIELD' flag can be set for chars, shorts, ints and long |
longs. If it is set, then the bitfield position is stored from bits |
VT_STRUCT_SHIFT to VT_STRUCT_SHIFT + 5 and the bit field size is stored |
from bits VT_STRUCT_SHIFT + 6 to VT_STRUCT_SHIFT + 11. |
`VT_LONG' is never used except during parsing. |
During parsing, the storage of an object is also stored in the type |
integer: |
#define VT_EXTERN 0x00000080 /* extern definition */ |
#define VT_STATIC 0x00000100 /* static variable */ |
#define VT_TYPEDEF 0x00000200 /* typedef definition */ |
#define VT_INLINE 0x00000400 /* inline definition */ |
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ |
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */ |
#define VT_WEAK 0x00010000 /* win32: data exported from dll */ |
8.5 Symbols |
=========== |
All symbols are stored in hashed symbol stacks. Each symbol stack |
contains `Sym' structures. |
`Sym.v' contains the symbol name (remember an idenfier is also a |
token, so a string is never necessary to store it). `Sym.t' gives the |
type of the symbol. `Sym.r' is usually the register in which the |
corresponding variable is stored. `Sym.c' is usually a constant |
associated to the symbol like its address for normal symbols, and the |
number of entries for symbols representing arrays. Variable length |
array types use `Sym.c' as a location on the stack which holds the |
runtime sizeof for the type. |
Four main symbol stacks are defined: |
`define_stack' |
for the macros (`#define's). |
`global_stack' |
for the global variables, functions and types. |
`local_stack' |
for the local variables, functions and types. |
`global_label_stack' |
for the local labels (for `goto'). |
`label_stack' |
for GCC block local labels (see the `__label__' keyword). |
`sym_push()' is used to add a new symbol in the local symbol stack. |
If no local symbol stack is active, it is added in the global symbol |
stack. |
`sym_pop(st,b)' pops symbols from the symbol stack ST until the |
symbol B is on the top of stack. If B is NULL, the stack is emptied. |
`sym_find(v)' return the symbol associated to the identifier V. The |
local stack is searched first from top to bottom, then the global stack. |
8.6 Sections |
============ |
The generated code and datas are written in sections. The structure |
`Section' contains all the necessary information for a given section. |
`new_section()' creates a new section. ELF file semantics is assumed |
for each section. |
The following sections are predefined: |
`text_section' |
is the section containing the generated code. IND contains the |
current position in the code section. |
`data_section' |
contains initialized data |
`bss_section' |
contains uninitialized data |
`bounds_section' |
`lbounds_section' |
are used when bound checking is activated |
`stab_section' |
`stabstr_section' |
are used when debugging is active to store debug information |
`symtab_section' |
`strtab_section' |
contain the exported symbols (currently only used for debugging). |
8.7 Code generation |
=================== |
8.7.1 Introduction |
------------------ |
The TCC code generator directly generates linked binary code in one |
pass. It is rather unusual these days (see gcc for example which |
generates text assembly), but it can be very fast and surprisingly |
little complicated. |
The TCC code generator is register based. Optimization is only done |
at the expression level. No intermediate representation of expression is |
kept except the current values stored in the _value stack_. |
On x86, three temporary registers are used. When more registers are |
needed, one register is spilled into a new temporary variable on the |
stack. |
8.7.2 The value stack |
--------------------- |
When an expression is parsed, its value is pushed on the value stack |
(VSTACK). The top of the value stack is VTOP. Each value stack entry is |
the structure `SValue'. |
`SValue.t' is the type. `SValue.r' indicates how the value is |
currently stored in the generated code. It is usually a CPU register |
index (`REG_xxx' constants), but additional values and flags are |
defined: |
#define VT_CONST 0x00f0 |
#define VT_LLOCAL 0x00f1 |
#define VT_LOCAL 0x00f2 |
#define VT_CMP 0x00f3 |
#define VT_JMP 0x00f4 |
#define VT_JMPI 0x00f5 |
#define VT_LVAL 0x0100 |
#define VT_SYM 0x0200 |
#define VT_MUSTCAST 0x0400 |
#define VT_MUSTBOUND 0x0800 |
#define VT_BOUNDED 0x8000 |
#define VT_LVAL_BYTE 0x1000 |
#define VT_LVAL_SHORT 0x2000 |
#define VT_LVAL_UNSIGNED 0x4000 |
#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED) |
`VT_CONST' |
indicates that the value is a constant. It is stored in the union |
`SValue.c', depending on its type. |
`VT_LOCAL' |
indicates a local variable pointer at offset `SValue.c.i' in the |
stack. |
`VT_CMP' |
indicates that the value is actually stored in the CPU flags (i.e. |
the value is the consequence of a test). The value is either 0 or |
1. The actual CPU flags used is indicated in `SValue.c.i'. |
If any code is generated which destroys the CPU flags, this value |
MUST be put in a normal register. |
`VT_JMP' |
`VT_JMPI' |
indicates that the value is the consequence of a conditional jump. |
For VT_JMP, it is 1 if the jump is taken, 0 otherwise. For VT_JMPI |
it is inverted. |
These values are used to compile the `||' and `&&' logical |
operators. |
If any code is generated, this value MUST be put in a normal |
register. Otherwise, the generated code won't be executed if the |
jump is taken. |
`VT_LVAL' |
is a flag indicating that the value is actually an lvalue (left |
value of an assignment). It means that the value stored is |
actually a pointer to the wanted value. |
Understanding the use `VT_LVAL' is very important if you want to |
understand how TCC works. |
`VT_LVAL_BYTE' |
`VT_LVAL_SHORT' |
`VT_LVAL_UNSIGNED' |
if the lvalue has an integer type, then these flags give its real |
type. The type alone is not enough in case of cast optimisations. |
`VT_LLOCAL' |
is a saved lvalue on the stack. `VT_LVAL' must also be set with |
`VT_LLOCAL'. `VT_LLOCAL' can arise when a `VT_LVAL' in a register |
has to be saved to the stack, or it can come from an |
architecture-specific calling convention. |
`VT_MUSTCAST' |
indicates that a cast to the value type must be performed if the |
value is used (lazy casting). |
`VT_SYM' |
indicates that the symbol `SValue.sym' must be added to the |
constant. |
`VT_MUSTBOUND' |
`VT_BOUNDED' |
are only used for optional bound checking. |
8.7.3 Manipulating the value stack |
---------------------------------- |
`vsetc()' and `vset()' pushes a new value on the value stack. If the |
previous VTOP was stored in a very unsafe place(for example in the CPU |
flags), then some code is generated to put the previous VTOP in a safe |
storage. |
`vpop()' pops VTOP. In some cases, it also generates cleanup code |
(for example if stacked floating point registers are used as on x86). |
The `gv(rc)' function generates code to evaluate VTOP (the top value |
of the stack) into registers. RC selects in which register class the |
value should be put. `gv()' is the _most important function_ of the |
code generator. |
`gv2()' is the same as `gv()' but for the top two stack entries. |
8.7.4 CPU dependent code generation |
----------------------------------- |
See the `i386-gen.c' file to have an example. |
`load()' |
must generate the code needed to load a stack value into a |
register. |
`store()' |
must generate the code needed to store a register into a stack |
value lvalue. |
`gfunc_start()' |
`gfunc_param()' |
`gfunc_call()' |
should generate a function call |
`gfunc_prolog()' |
`gfunc_epilog()' |
should generate a function prolog/epilog. |
`gen_opi(op)' |
must generate the binary integer operation OP on the two top |
entries of the stack which are guaranted to contain integer types. |
The result value should be put on the stack. |
`gen_opf(op)' |
same as `gen_opi()' for floating point operations. The two top |
entries of the stack are guaranted to contain floating point |
values of same types. |
`gen_cvt_itof()' |
integer to floating point conversion. |
`gen_cvt_ftoi()' |
floating point to integer conversion. |
`gen_cvt_ftof()' |
floating point to floating point of different size conversion. |
`gen_bounded_ptr_add()' |
`gen_bounded_ptr_deref()' |
are only used for bounds checking. |
8.8 Optimizations done |
====================== |
Constant propagation is done for all operations. Multiplications and |
divisions are optimized to shifts when appropriate. Comparison |
operators are optimized by maintaining a special cache for the |
processor flags. &&, || and ! are optimized by maintaining a special |
'jump target' value. No other jump optimization is currently performed |
because it would require to store the code in a more abstract fashion. |
Concept Index |
************* |