C-sparse
view release on metacpan or search on metacpan
src/sparse-0.4.4/compile-i386.c view on Meta::CPAN
REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
REGINFO( SI, "%si", ESI, ESI_EDI),
REGINFO( DI, "%di", EDI, ESI_EDI),
REGINFO( BP, "%bp", EBP),
REGINFO( SP, "%sp", ESP),
REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
REGINFO(ESI, "%esi", SI, ESI_EDI),
REGINFO(EDI, "%edi", DI, ESI_EDI),
REGINFO(EBP, "%ebp", BP),
REGINFO(ESP, "%esp", SP),
REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
};
#define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
static struct storage hardreg_storage_table[] = {
REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
};
#define REG_EAX (&hardreg_storage_table[EAX])
#define REG_ECX (&hardreg_storage_table[ECX])
#define REG_EDX (&hardreg_storage_table[EDX])
#define REG_ESP (&hardreg_storage_table[ESP])
#define REG_DL (&hardreg_storage_table[DL])
#define REG_DX (&hardreg_storage_table[DX])
#define REG_AL (&hardreg_storage_table[AL])
#define REG_AX (&hardreg_storage_table[AX])
static DECLARE_BITMAP(regs_in_use, 256);
static inline struct storage * reginfo_reg(struct reg_info *info)
{
return hardreg_storage_table + info->own_regno;
}
static struct storage * get_hardreg(SCTX_ struct storage *reg, int clear)
{
struct reg_info *info = reg->reg;
const unsigned char *aliases;
int regno;
aliases = info->aliases;
while ((regno = *aliases++) != NOREG) {
if (test_bit(regno, regs_in_use))
goto busy;
if (clear)
reg_info_table[regno].contains = NULL;
}
set_bit(info->own_regno, regs_in_use);
return reg;
busy:
fprintf(stderr, "register %s is busy\n", info->name);
if (regno + reg_info_table != info)
fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
exit(1);
}
static void put_reg(SCTX_ struct storage *reg)
{
struct reg_info *info = reg->reg;
int regno = info->own_regno;
if (test_and_clear_bit(regno, regs_in_use))
return;
fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
}
struct regclass {
const char *name;
const unsigned char regs[30];
};
static struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
static struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
static struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
static struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
static struct regclass *get_regclass_bits(SCTX_ int bits)
{
switch (bits) {
case 8: return ®class_8;
case 16: return ®class_16;
case 64: return ®class_64;
default: return ®class_32;
}
}
static struct regclass *get_regclass(SCTX_ struct expression *expr)
{
return get_regclass_bits(sctx_ expr->ctype->bit_size);
}
static int register_busy(SCTX_ int regno)
{
if (!test_bit(regno, regs_in_use)) {
struct reg_info *info = reg_info_table + regno;
const unsigned char *regs = info->aliases+1;
while ((regno = *regs) != NOREG) {
regs++;
if (test_bit(regno, regs_in_use))
goto busy;
}
return 0;
}
busy:
return 1;
}
static struct storage *get_reg(SCTX_ struct regclass *class)
{
const unsigned char *regs = class->regs;
int regno;
while ((regno = *regs) != NOREG) {
regs++;
if (register_busy(sctx_ regno))
continue;
return get_hardreg(sctx_ hardreg_storage_table + regno, 1);
}
fprintf(stderr, "Ran out of %s registers\n", class->name);
exit(1);
}
static struct storage *get_reg_value(SCTX_ struct storage *value, struct regclass *class)
{
struct reg_info *info;
struct storage *reg;
/* Do we already have it somewhere */
info = value->reg;
if (info && info->contains == value) {
emit_comment(sctx_ "already have register %s", info->name);
return get_hardreg(sctx_ hardreg_storage_table + info->own_regno, 0);
}
reg = get_reg(sctx_ class);
emit_move(sctx_ value, reg, value->ctype, "reload register");
info = reg->reg;
info->contains = value;
value->reg = info;
return reg;
}
static struct storage *temp_from_bits(SCTX_ unsigned int bit_size)
{
return get_reg(sctx_ get_regclass_bits(sctx_ bit_size));
}
static inline unsigned int pseudo_offset(struct storage *s)
{
if (s->type != STOR_PSEUDO)
return 123456; /* intentionally bogus value */
return s->offset;
}
static inline unsigned int arg_offset(struct storage *s)
{
if (s->type != STOR_ARG)
return 123456; /* intentionally bogus value */
/* FIXME: this is wrong wrong wrong */
return current_func->stack_size + ((1 + s->idx) * 4);
}
static const char *pretty_offset(SCTX_ int ofs)
{
static char esp_buf[64];
if (ofs)
sprintf(esp_buf, "%d(%%esp)", ofs);
else
strcpy(esp_buf, "(%esp)");
return esp_buf;
}
( run in 1.822 second using v1.01-cache-2.11-cpan-39bf76dae61 )