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 &regclass_8;
	case 16: return &regclass_16;
	case 64: return &regclass_64;
	default: return &regclass_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 )