added better relocation support (needed for file output)
This commit is contained in:
		
							parent
							
								
									7ab1ac48bb
								
							
						
					
					
						commit
						6cd36b1285
					
				
					 2 changed files with 462 additions and 297 deletions
				
			
		
							
								
								
									
										43
									
								
								i386-gen.c
									
										
									
									
									
								
							
							
						
						
									
										43
									
								
								i386-gen.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  X86 code generator for TCC
 | 
					 *  X86 code generator for TCC
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 *  Copyright (c) 2001 Fabrice Bellard
 | 
					 *  Copyright (c) 2001, 2002 Fabrice Bellard
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  This program is free software; you can redistribute it and/or modify
 | 
					 *  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
 | 
					 *  it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,9 @@ int reg_classes[NB_REGS] = {
 | 
				
			||||||
#define LDOUBLE_SIZE  12
 | 
					#define LDOUBLE_SIZE  12
 | 
				
			||||||
#define LDOUBLE_ALIGN 4
 | 
					#define LDOUBLE_ALIGN 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* relocation type for 32 bit data relocation */
 | 
				
			||||||
 | 
					#define R_DATA_32 R_386_32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* function call context */
 | 
					/* function call context */
 | 
				
			||||||
typedef struct GFuncContext {
 | 
					typedef struct GFuncContext {
 | 
				
			||||||
    int args_size;
 | 
					    int args_size;
 | 
				
			||||||
| 
						 | 
					@ -101,21 +104,21 @@ void gen_le32(int c)
 | 
				
			||||||
    g(c >> 24);
 | 
					    g(c >> 24);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* patch relocation entry with value 'val' */
 | 
					void greloc_patch(unsigned char *ptr, 
 | 
				
			||||||
void greloc_patch1(Reloc *p, int val)
 | 
					                  unsigned long addr, unsigned long val, int type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch(p->type) {
 | 
					    switch(type) {
 | 
				
			||||||
    case RELOC_ADDR32:
 | 
					    case R_386_32:
 | 
				
			||||||
        *(int *)p->addr = val;
 | 
					        *(int *)ptr += val;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case RELOC_REL32:
 | 
					    case R_386_PC32:
 | 
				
			||||||
        *(int *)p->addr = val - p->addr - 4;
 | 
					        *(int *)ptr += val - addr - 4;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* output a symbol and patch all calls to it */
 | 
					/* output a symbol and patch all calls to it */
 | 
				
			||||||
void gsym_addr(t, a)
 | 
					void gsym_addr(int t, int a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int n;
 | 
					    int n;
 | 
				
			||||||
    while (t) {
 | 
					    while (t) {
 | 
				
			||||||
| 
						 | 
					@ -125,7 +128,7 @@ void gsym_addr(t, a)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void gsym(t)
 | 
					void gsym(int t)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gsym_addr(t, ind);
 | 
					    gsym_addr(t, ind);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -144,13 +147,14 @@ int oad(int c, int s)
 | 
				
			||||||
    return s;
 | 
					    return s;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* output constant with relocation if 'r & VT_FORWARD' is true */
 | 
					/* output constant with relocation if 'r & VT_SYM' is true */
 | 
				
			||||||
void gen_addr32(int r, int c)
 | 
					void gen_addr32(int r, int c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!(r & VT_FORWARD)) {
 | 
					    if (!(r & VT_SYM)) {
 | 
				
			||||||
        gen_le32(c);
 | 
					        gen_le32(c);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        greloc((Sym *)c, ind, RELOC_ADDR32);
 | 
					        greloc(cur_text_section, 
 | 
				
			||||||
 | 
					               (Sym *)c, ind - (int)cur_text_section->data, R_386_32);
 | 
				
			||||||
        gen_le32(0);
 | 
					        gen_le32(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -347,9 +351,10 @@ void gfunc_call(GFuncContext *c)
 | 
				
			||||||
    int r;
 | 
					    int r;
 | 
				
			||||||
    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
 | 
					    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
 | 
				
			||||||
        /* constant case */
 | 
					        /* constant case */
 | 
				
			||||||
        /* forward reference */
 | 
					        if (vtop->r & VT_SYM) {
 | 
				
			||||||
        if (vtop->r & VT_FORWARD) {
 | 
					            /* relocation case */
 | 
				
			||||||
            greloc(vtop->c.sym, ind + 1, RELOC_REL32);
 | 
					            greloc(cur_text_section, vtop->c.sym, 
 | 
				
			||||||
 | 
					                   ind + 1 - (int)cur_text_section->data, R_386_PC32);
 | 
				
			||||||
            oad(0xe8, 0);
 | 
					            oad(0xe8, 0);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            oad(0xe8, vtop->c.ul - ind - 5);
 | 
					            oad(0xe8, vtop->c.ul - ind - 5);
 | 
				
			||||||
| 
						 | 
					@ -485,7 +490,7 @@ int gtst(int inv, int t)
 | 
				
			||||||
            vpushi(0);
 | 
					            vpushi(0);
 | 
				
			||||||
            gen_op(TOK_NE);
 | 
					            gen_op(TOK_NE);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
 | 
					        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
 | 
				
			||||||
            /* constant jmp optimization */
 | 
					            /* constant jmp optimization */
 | 
				
			||||||
            if ((vtop->c.i != 0) != inv) 
 | 
					            if ((vtop->c.i != 0) != inv) 
 | 
				
			||||||
                t = gjmp(t);
 | 
					                t = gjmp(t);
 | 
				
			||||||
| 
						 | 
					@ -511,7 +516,7 @@ void gen_opi(int op)
 | 
				
			||||||
    case TOK_ADDC1: /* add with carry generation */
 | 
					    case TOK_ADDC1: /* add with carry generation */
 | 
				
			||||||
        opc = 0;
 | 
					        opc = 0;
 | 
				
			||||||
    gen_op8:
 | 
					    gen_op8:
 | 
				
			||||||
        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
 | 
					        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
 | 
				
			||||||
            /* constant case */
 | 
					            /* constant case */
 | 
				
			||||||
            vswap();
 | 
					            vswap();
 | 
				
			||||||
            r = gv(RC_INT);
 | 
					            r = gv(RC_INT);
 | 
				
			||||||
| 
						 | 
					@ -576,7 +581,7 @@ void gen_opi(int op)
 | 
				
			||||||
        opc = 7;
 | 
					        opc = 7;
 | 
				
			||||||
    gen_shift:
 | 
					    gen_shift:
 | 
				
			||||||
        opc = 0xc0 | (opc << 3);
 | 
					        opc = 0xc0 | (opc << 3);
 | 
				
			||||||
        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
 | 
					        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
 | 
				
			||||||
            /* constant case */
 | 
					            /* constant case */
 | 
				
			||||||
            vswap();
 | 
					            vswap();
 | 
				
			||||||
            r = gv(RC_INT);
 | 
					            r = gv(RC_INT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue