36 lines
2.1 KiB
C
36 lines
2.1 KiB
C
#pragma once
|
|
|
|
// Can expression be expressed as a single x86 operand?
|
|
#define XOP_NOT_XOP 0
|
|
#define XOP_NOT_MEM 1
|
|
#define XOP_MEM 2
|
|
static inline int is_xop(AST *e) {
|
|
if(e->nodeKind == AST_EXPR_PRIMITIVE) {
|
|
return XOP_NOT_MEM;
|
|
} else if(e->nodeKind == AST_EXPR_VAR) {
|
|
return e->exprVar.thing->kind == VARTABLEENTRY_VAR ? XOP_NOT_MEM : XOP_MEM;
|
|
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF && e->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && e->exprUnOp.operand->exprBinOp.operator == BINOP_ADD && e->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprVar.thing->kind == VARTABLEENTRY_VAR && e->exprUnOp.operand->exprBinOp.operands[1]->exprVar.thing->kind == VARTABLEENTRY_VAR) {
|
|
return XOP_MEM;
|
|
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_REF && e->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_SYMBOL) {
|
|
return XOP_NOT_MEM;
|
|
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF) {
|
|
AST *c = e->exprUnOp.operand;
|
|
|
|
if(c->nodeKind == AST_EXPR_VAR && c->exprVar.thing->kind == VARTABLEENTRY_VAR) {
|
|
return XOP_MEM;
|
|
} else if(c->nodeKind == AST_EXPR_BINARY_OP && c->exprBinOp.operator == BINOP_ADD && c->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && c->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && c->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR) {
|
|
if(c->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR) {
|
|
return XOP_MEM;
|
|
} else if(c->exprBinOp.operands[1]->nodeKind == AST_EXPR_BINARY_OP && c->exprBinOp.operands[1]->exprBinOp.operator == BINOP_MUL && c->exprBinOp.operands[1]->exprBinOp.operands[0]->nodeKind == AST_EXPR_PRIMITIVE && c->exprBinOp.operands[1]->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR) {
|
|
int scale = c->exprBinOp.operands[1]->exprBinOp.operands[0]->exprPrim.val;
|
|
|
|
if(scale == 1 || scale == 2 || scale == 4 || scale == 8) {
|
|
return XOP_MEM;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return XOP_NOT_XOP;
|
|
}
|