mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-23 21:41:34 +00:00
Allow for [base - disp]
This commit is contained in:
@@ -1107,6 +1107,29 @@ gb_internal void check_asm_instruction_operand(AsmCtx *asm_ctx, CheckerContext *
|
||||
check_asm_instruction_operand(asm_ctx, ctx, entity, &scale, mem_op->scale, false);
|
||||
check_asm_instruction_operand(asm_ctx, ctx, entity, &disp, mem_op->disp, false);
|
||||
|
||||
// NOTE(bill): if the index is actually an immediate and there is no scale nor disp,
|
||||
// then treat it as a disp, and modify the AST too
|
||||
if (index.expr != nullptr && scale.expr == nullptr && disp.expr == nullptr) {
|
||||
bool do_swap = index.mode == Addressing_Constant;
|
||||
if (!do_swap) {
|
||||
Entity *param_entity = entity_of_node(index.expr);
|
||||
if (param_entity != nullptr && param_entity->kind == Entity_Variable) {
|
||||
auto kind = check_asm_find_kind(param_entity, ate->decls);
|
||||
do_swap = kind == AsmTemplateEntityDecl_Immediate;
|
||||
}
|
||||
}
|
||||
if (do_swap) {
|
||||
disp = index;
|
||||
index = {};
|
||||
|
||||
mem_op->disp = mem_op->index;
|
||||
mem_op->index = nullptr;
|
||||
|
||||
mem_op->disp_op = mem_op->index_op;
|
||||
mem_op->index_op = {};
|
||||
}
|
||||
}
|
||||
|
||||
i32 base_w = 0;
|
||||
i32 index_w = 0;
|
||||
bool have_base = false;
|
||||
|
||||
@@ -8,6 +8,9 @@ struct lbAsmGenerate {
|
||||
WriteOperandFlag_IsScale = 1<<1,
|
||||
WriteOperandFlag_IsScaleLog2 = 1<<2,
|
||||
|
||||
WriteOperandFlag_Negate = 1<<3,
|
||||
|
||||
|
||||
WriteOperandFlag_NONE = 0,
|
||||
WriteOperandFlag_DEFAULT = WriteOperandFlag_PrintPrefixes,
|
||||
};
|
||||
@@ -77,6 +80,10 @@ struct lbAsmGenerate {
|
||||
asm_string = gb_string_appendc(asm_string, "$$");
|
||||
}
|
||||
|
||||
if (flags & WriteOperandFlag_Negate) {
|
||||
val = -val;
|
||||
}
|
||||
|
||||
asm_string = gb_string_append_fmt(asm_string, "%d", cast(int)val);
|
||||
break;
|
||||
}
|
||||
@@ -97,6 +104,11 @@ struct lbAsmGenerate {
|
||||
return write_constant_operand(asm_string, op, flags);
|
||||
}
|
||||
|
||||
if (flags & WriteOperandFlag_Negate) {
|
||||
flags &= ~WriteOperandFlag_Negate;
|
||||
asm_string = gb_string_appendc(asm_string, "-");
|
||||
}
|
||||
|
||||
switch (op->kind) {
|
||||
case_ast_node(i, Ident, op);
|
||||
Entity *e = entity_of_node(op);
|
||||
@@ -276,14 +288,25 @@ struct lbAsmGenerate_amd64 : lbAsmGenerate {
|
||||
|
||||
gbString write_memory_operand(gbString asm_string, Slice<i32> const &op_number, AstAsmMemoryOperand *mem_op, u32 flags) override {
|
||||
if (mem_op->disp) {
|
||||
asm_string = this->write_operand(asm_string, op_number, mem_op->disp, flags&~WriteOperandFlag_PrintPrefixes);
|
||||
u32 disp_flags = flags;
|
||||
disp_flags &= ~WriteOperandFlag_PrintPrefixes;
|
||||
if (mem_op->disp_op.kind == Token_Sub) {
|
||||
disp_flags |= WriteOperandFlag_Negate;
|
||||
}
|
||||
|
||||
asm_string = this->write_operand(asm_string, op_number, mem_op->disp, disp_flags);
|
||||
}
|
||||
asm_string = gb_string_appendc(asm_string, "(");
|
||||
GB_ASSERT(mem_op->base != nullptr);
|
||||
asm_string = this->write_operand(asm_string, op_number, mem_op->base, flags);
|
||||
if (mem_op->index) {
|
||||
u32 index_flags = flags;
|
||||
if (mem_op->index_op.kind == Token_Sub) {
|
||||
index_flags |= WriteOperandFlag_Negate;
|
||||
}
|
||||
asm_string = gb_string_appendc(asm_string, ",");
|
||||
asm_string = this->write_operand(asm_string, op_number, mem_op->index, flags);
|
||||
asm_string = this->write_operand(asm_string, op_number, mem_op->index, index_flags);
|
||||
|
||||
if (mem_op->scale) {
|
||||
asm_string = gb_string_appendc(asm_string, ",");
|
||||
switch (mem_op->scale_op.kind) {
|
||||
@@ -634,7 +657,7 @@ struct lbAsmGenerate_amd64 : lbAsmGenerate {
|
||||
|
||||
LLVMValueRef call = LLVMBuildCall2(p->builder, fn_ty, ia, call_args.data, cast(unsigned)call_args.count, "");
|
||||
|
||||
if (false) {
|
||||
if (true) {
|
||||
// DEBUG PRINT!!!
|
||||
// DEBUG PRINT!!!
|
||||
// DEBUG PRINT!!!
|
||||
|
||||
@@ -2489,16 +2489,21 @@ gb_internal Ast *parse_asm_operand(AstFile *f, bool allow_memory_operand) {
|
||||
Ast *disp = nullptr;
|
||||
Ast *type = nullptr;
|
||||
|
||||
Token index_op = {};
|
||||
Token scale_op = {};
|
||||
Token disp_op = {};
|
||||
|
||||
base = parse_asm_operand(f, false);
|
||||
|
||||
// [base]
|
||||
// [base + index]
|
||||
// [base - index]
|
||||
// [base + index + disp]
|
||||
// [base + index*scale] // *, <<, >>
|
||||
// [base + index*scale + disp]
|
||||
if (allow_token(f, Token_Add)) {
|
||||
if (allow_token(f, Token_Add) ||
|
||||
allow_token(f, Token_Sub)) {
|
||||
index_op = f->prev_token;
|
||||
index = parse_asm_operand(f, false);
|
||||
if (allow_token(f, Token_Mul) ||
|
||||
allow_token(f, Token_Shl) ||
|
||||
@@ -2506,7 +2511,9 @@ gb_internal Ast *parse_asm_operand(AstFile *f, bool allow_memory_operand) {
|
||||
scale_op = f->prev_token;
|
||||
scale = parse_asm_operand(f, false);
|
||||
}
|
||||
if (allow_token(f, Token_Add)) {
|
||||
if (allow_token(f, Token_Add) ||
|
||||
allow_token(f, Token_Sub)) {
|
||||
disp_op = f->prev_token;
|
||||
disp = parse_asm_operand(f, false);
|
||||
}
|
||||
}
|
||||
@@ -2521,9 +2528,11 @@ gb_internal Ast *parse_asm_operand(AstFile *f, bool allow_memory_operand) {
|
||||
Ast *mem = alloc_ast_node(f, Ast_AsmMemoryOperand);
|
||||
mem->AsmMemoryOperand.open = open;
|
||||
mem->AsmMemoryOperand.base = base;
|
||||
mem->AsmMemoryOperand.index_op = index_op;
|
||||
mem->AsmMemoryOperand.index = index;
|
||||
mem->AsmMemoryOperand.scale = scale;
|
||||
mem->AsmMemoryOperand.scale_op = scale_op;
|
||||
mem->AsmMemoryOperand.scale = scale;
|
||||
mem->AsmMemoryOperand.disp_op = disp_op;
|
||||
mem->AsmMemoryOperand.disp = disp;
|
||||
mem->AsmMemoryOperand.close = close;
|
||||
mem->AsmMemoryOperand.type = type;
|
||||
|
||||
@@ -511,9 +511,11 @@ struct AstSplitArgs {
|
||||
AST_KIND(AsmMemoryOperand, "asm memory operand", struct { \
|
||||
Token open; \
|
||||
Ast * base; \
|
||||
Token index_op; \
|
||||
Ast * index; \
|
||||
Token scale_op; \
|
||||
Ast * scale; \
|
||||
Token disp_op; \
|
||||
Ast * disp; \
|
||||
Ast * type; \
|
||||
Token close; \
|
||||
|
||||
Reference in New Issue
Block a user