mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-22 11:41:38 +00:00
[qfcc] Rewrite assignment destination addressing
It now addressing_mode cleaning up store instructions to use ptr+offset instead of lea;store ptr... Entity.field addressing has been impelmented as well. Move instructions still generate sub-optimal code in that they use an add instruction instead of lea.
This commit is contained in:
parent
d3764c108a
commit
284fcd312d
1 changed files with 22 additions and 31 deletions
|
@ -792,17 +792,6 @@ operand_address (operand_t *reference, expr_t *e)
|
||||||
op_type_names[reference->op_type]);
|
op_type_names[reference->op_type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((pure)) int
|
|
||||||
is_const_ptr (expr_t *e)
|
|
||||||
{
|
|
||||||
if ((e->type != ex_value || e->e.value->lltype != ev_ptr)
|
|
||||||
|| !(POINTER_VAL (e->e.value->v.pointer) >= 0
|
|
||||||
&& POINTER_VAL (e->e.value->v.pointer) < 65536)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __attribute__((pure)) int
|
static __attribute__((pure)) int
|
||||||
is_indirect (expr_t *e)
|
is_indirect (expr_t *e)
|
||||||
{
|
{
|
||||||
|
@ -813,6 +802,10 @@ is_indirect (expr_t *e)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static sblock_t *addressing_mode (sblock_t *sblock, expr_t *ref,
|
||||||
|
operand_t **base, operand_t **offset,
|
||||||
|
pr_ushort_t *mode);
|
||||||
|
|
||||||
static sblock_t *
|
static sblock_t *
|
||||||
expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
|
expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
|
||||||
{
|
{
|
||||||
|
@ -916,6 +909,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
operand_t *src = 0;
|
operand_t *src = 0;
|
||||||
operand_t *dst = 0;
|
operand_t *dst = 0;
|
||||||
operand_t *ofs = 0;
|
operand_t *ofs = 0;
|
||||||
|
pr_ushort_t mode = 0; // assign
|
||||||
const char *opcode = "assign";
|
const char *opcode = "assign";
|
||||||
st_type_t type;
|
st_type_t type;
|
||||||
|
|
||||||
|
@ -957,26 +951,10 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
|
|
||||||
if (0) {
|
if (0) {
|
||||||
dereference_dst:
|
dereference_dst:
|
||||||
// dst_expr is a dereferenced pointer, so need to un-dereference it
|
// dst_expr is a dereferenced pointer, so need to get its addressing
|
||||||
// to get the pointer and switch to storep instructions.
|
// parameters (base and offset) and switch to storep instructions.
|
||||||
dst_expr = expr_file_line (address_expr (dst_expr, 0), e);
|
sblock = addressing_mode (sblock, dst_expr, &dst, &ofs, &mode);
|
||||||
opcode = "store";
|
opcode = "store";
|
||||||
if (dst_expr->type == ex_address && dst_expr->e.address.offset
|
|
||||||
&& !is_const_ptr (dst_expr->e.address.lvalue)) {
|
|
||||||
sblock = statement_subexpr (sblock,
|
|
||||||
dst_expr->e.address.lvalue, &dst);
|
|
||||||
sblock = statement_subexpr (sblock,
|
|
||||||
dst_expr->e.address.offset, &ofs);
|
|
||||||
} else {
|
|
||||||
sblock = statement_subexpr (sblock, dst_expr, &dst);
|
|
||||||
if (options.code.progsversion < PROG_VERSION) {
|
|
||||||
// v6 and v6p stores don't need an index
|
|
||||||
ofs = 0;
|
|
||||||
} else {
|
|
||||||
// ruamoko stores do need an index
|
|
||||||
ofs = short_operand (0, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type = st_ptrassign;
|
type = st_ptrassign;
|
||||||
}
|
}
|
||||||
if (op) {
|
if (op) {
|
||||||
|
@ -987,6 +965,10 @@ dereference_dst:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_entity (dst->type) && ofs && is_field (ofs->type)) {
|
if (is_entity (dst->type) && ofs && is_field (ofs->type)) {
|
||||||
|
// need to get a pointer type, entity.field expressions do not provide
|
||||||
|
// one directly. FIXME it was probably a mistake extracting the operand
|
||||||
|
// type from the statement expression in dags
|
||||||
|
dst_expr = expr_file_line (address_expr (dst_expr, 0), dst_expr);
|
||||||
s = new_statement (st_expr, "lea", dst_expr);
|
s = new_statement (st_expr, "lea", dst_expr);
|
||||||
s->opa = dst;
|
s->opa = dst;
|
||||||
s->opb = ofs;
|
s->opb = ofs;
|
||||||
|
@ -1316,7 +1298,16 @@ addressing_mode (sblock_t *sblock, expr_t *ref,
|
||||||
// ref is known to be either ex_expr or ex_uexpr, with '.' for
|
// ref is known to be either ex_expr or ex_uexpr, with '.' for
|
||||||
// the operator
|
// the operator
|
||||||
if (ref->type == ex_expr) {
|
if (ref->type == ex_expr) {
|
||||||
internal_error (ref, "not implemented");
|
expr_t *ent_expr = ref->e.expr.e1;
|
||||||
|
expr_t *fld_expr = ref->e.expr.e2;
|
||||||
|
if (!is_entity (get_type (ent_expr))
|
||||||
|
|| !is_field (get_type (fld_expr))) {
|
||||||
|
print_expr (ref);
|
||||||
|
internal_error (ref, "expected entity.field");
|
||||||
|
}
|
||||||
|
sblock = statement_subexpr (sblock, ent_expr, base);
|
||||||
|
sblock = statement_subexpr (sblock, fld_expr, offset);
|
||||||
|
*mode = 1;//entity.field
|
||||||
} else if (ref->type == ex_uexpr) {
|
} else if (ref->type == ex_uexpr) {
|
||||||
sblock = ptr_addressing_mode (sblock, ref->e.expr.e1, base, offset,
|
sblock = ptr_addressing_mode (sblock, ref->e.expr.e1, base, offset,
|
||||||
mode);
|
mode);
|
||||||
|
|
Loading…
Reference in a new issue