mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-26 08:00:09 +08:00
added better relocation support (needed for file output)
This commit is contained in:
parent
7ab1ac48bb
commit
6cd36b1285
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…
Reference in New Issue
Block a user