summaryrefslogtreecommitdiffhomepage
path: root/ir/be
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2019-03-25 20:18:07 +0100
committerChristoph Mallon <christoph.mallon@gmx.de>2019-03-25 20:18:07 +0100
commite3359952fb04bff07900230dcb81c1c00335b807 (patch)
tree4ddd1c236229008742806da9c2be9f57f4c11358 /ir/be
parent026e48ad8cbd83a608c1132443fa5064c0bb686a (diff)
amd64, ia32: Support all address modes in inline asm.
Diffstat (limited to 'ir/be')
-rw-r--r--ir/be/amd64/amd64_emitter.c7
-rw-r--r--ir/be/beasm.h15
-rw-r--r--ir/be/ia32/ia32_emitter.c7
-rw-r--r--ir/be/ia32/x86_asm.c27
-rw-r--r--ir/be/ia32/x86_asm.h6
5 files changed, 43 insertions, 19 deletions
diff --git a/ir/be/amd64/amd64_emitter.c b/ir/be/amd64/amd64_emitter.c
index a786361..20ea772 100644
--- a/ir/be/amd64/amd64_emitter.c
+++ b/ir/be/amd64/amd64_emitter.c
@@ -562,12 +562,9 @@ static void emit_amd64_asm_operand(ir_node const *const node, char const modifie
return;
}
- case BE_ASM_OPERAND_MEMORY: {
- arch_register_t const *const reg
- = arch_get_irn_register_in(node, op->op.pos);
- be_emit_irprintf("(%%%s)", reg->name);
+ case BE_ASM_OPERAND_MEMORY:
+ x86_emit_addr(node, &op->u.addr);
return;
- }
case BE_ASM_OPERAND_IMMEDIATE:
if (!be_has_modifier("Pcp", modifier))
diff --git a/ir/be/beasm.h b/ir/be/beasm.h
index d7fe333..33af771 100644
--- a/ir/be/beasm.h
+++ b/ir/be/beasm.h
@@ -35,7 +35,7 @@ typedef struct be_asm_operand_t {
static inline void be_set_asm_operand(be_asm_operand_t* const op, be_asm_operand_kind_t const kind, int const pos)
{
- assert((kind == BE_ASM_OPERAND_IMMEDIATE) == (pos == -1));
+ assert(pos == -1 ? kind == BE_ASM_OPERAND_IMMEDIATE || kind == BE_ASM_OPERAND_MEMORY : kind != BE_ASM_OPERAND_IMMEDIATE);
op->kind = kind;
op->pos = pos;
}
@@ -71,12 +71,19 @@ typedef struct be_asm_info_t {
be_asm_info_t be_asm_prepare_info(ir_node const *node);
-static inline void be_asm_add_in(be_asm_info_t *const info, be_asm_operand_t *const op, be_asm_operand_kind_t const kind, ir_node *const in, arch_register_req_t const *const req)
+static inline size_t be_asm_append_in(be_asm_info_t *const info, ir_node *const in, arch_register_req_t const *const req)
{
- assert(kind == BE_ASM_OPERAND_INPUT_VALUE || kind == BE_ASM_OPERAND_MEMORY);
- be_set_asm_operand(op, kind, ARR_LEN(info->ins));
+ size_t const pos = ARR_LEN(info->ins);
ARR_APP1(ir_node*, info->ins, in);
ARR_APP1(arch_register_req_t const*, info->in_reqs, req);
+ return pos;
+}
+
+static inline void be_asm_add_in(be_asm_info_t *const info, be_asm_operand_t *const op, be_asm_operand_kind_t const kind, ir_node *const in, arch_register_req_t const *const req)
+{
+ assert(kind == BE_ASM_OPERAND_INPUT_VALUE || kind == BE_ASM_OPERAND_MEMORY);
+ size_t const pos = be_asm_append_in(info, in, req);
+ be_set_asm_operand(op, kind, pos);
}
static inline arch_register_req_t const *be_asm_make_same_req(struct obstack *const obst, arch_register_req_t const *const req, unsigned const pos)
diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c
index 9eafdb7..121f0a4 100644
--- a/ir/be/ia32/ia32_emitter.c
+++ b/ir/be/ia32/ia32_emitter.c
@@ -784,12 +784,9 @@ static void emit_ia32_asm_operand(ir_node const *const node, char const modifier
return;
}
- case BE_ASM_OPERAND_MEMORY: {
- arch_register_t const *const reg
- = arch_get_irn_register_in(node, op->op.pos);
- be_emit_irprintf("(%%%s)", reg->name);
+ case BE_ASM_OPERAND_MEMORY:
+ x86_emit_addr(node, &op->u.addr);
return;
- }
case BE_ASM_OPERAND_IMMEDIATE:
if (!be_has_modifier("Pcp", modifier))
diff --git a/ir/be/ia32/x86_asm.c b/ir/be/ia32/x86_asm.c
index 1f0fda6..e8ce6ef 100644
--- a/ir/be/ia32/x86_asm.c
+++ b/ir/be/ia32/x86_asm.c
@@ -63,6 +63,13 @@ static void x86_parse_constraint_letter(void const *const env, be_asm_constraint
panic("Unknown asm constraint '%c'", l);
}
+static size_t x86_add_addr_in(be_asm_info_t *const info, ir_node *const in)
+{
+ ir_node *const new_in = be_transform_node(in);
+ arch_register_req_t const *const req = arch_get_irn_register_req(new_in)->cls->class_req;
+ return be_asm_append_in(info, new_in, req);
+}
+
ir_node *x86_match_ASM(ir_node const *const node, x86_asm_constraint_list_t const *const constraint_list)
{
be_asm_info_t info = be_asm_prepare_info(node);
@@ -95,9 +102,23 @@ ir_node *x86_match_ASM(ir_node const *const node, x86_asm_constraint_list_t cons
arch_register_req_t const *const ireq = be_make_register_req(obst, &be_constraint);
be_asm_add_inout(&info, &op->op, obst, in, ireq, c->out_pos);
} else {
- ir_node *const new_in = be_transform_node(in);
- arch_register_req_t const *const ireq = arch_get_irn_register_req(new_in)->cls->class_req;
- be_asm_add_in(&info, &op->op, BE_ASM_OPERAND_MEMORY, new_in, ireq);
+ x86_address_t address;
+ x86_create_address_mode(&address, in, x86_create_am_normal);
+
+ x86_addr_t *const addr = &op->u.addr;
+ *addr = (x86_addr_t){
+ .immediate = address.imm,
+ .log_scale = address.scale,
+ .variant = address.variant,
+ };
+
+ if (x86_addr_variant_has_base(address.variant))
+ addr->base_input = x86_add_addr_in(&info, address.base);
+
+ if (x86_addr_variant_has_index(address.variant))
+ addr->index_input = x86_add_addr_in(&info, address.index);
+
+ be_set_asm_operand(&op->op, BE_ASM_OPERAND_MEMORY, -1);
}
} else {
be_asm_add_out(&info, &op->op, obst, &be_constraint, c->out_pos);
diff --git a/ir/be/ia32/x86_asm.h b/ir/be/ia32/x86_asm.h
index fae9ff0..bfbdf14 100644
--- a/ir/be/ia32/x86_asm.h
+++ b/ir/be/ia32/x86_asm.h
@@ -19,13 +19,15 @@
#include "compiler.h"
#include "firm_types.h"
#include "util.h"
+#include "x86_address_mode.h"
#include "x86_node.h"
typedef struct x86_asm_operand_t {
be_asm_operand_t op;
union {
- ir_mode *mode;
- x86_imm32_t imm32;
+ ir_mode *mode;
+ x86_imm32_t imm32;
+ x86_addr_t addr;
} u;
} x86_asm_operand_t;