Commit 69d4cb08 authored by Matthias Braun's avatar Matthias Braun
Browse files

more work on ia32 assembler nodes

[r14270]
parent 930ef5ed
...@@ -1311,18 +1311,135 @@ void emit_Jmp(ia32_emit_env_t *env, const ir_node *node) { ...@@ -1311,18 +1311,135 @@ void emit_Jmp(ia32_emit_env_t *env, const ir_node *node) {
be_emit_finish_line_gas(env, node); be_emit_finish_line_gas(env, node);
} }
static
const char* emit_asm_operand(ia32_emit_env_t *env, const ir_node *node,
const char *s)
{
const arch_register_t *reg;
const char *reg_name;
char c;
char modifier = 0;
int num = -1;
ia32_attr_t *attr;
int n_outs;
int p;
assert(*s == '%');
c = *(++s);
/* parse modifiers */
switch(c) {
case 0:
ir_fprintf(stderr, "Warning: asm text (%+F) ends with %\n", node);
be_emit_char(env, '%');
return s + 1;
case '%':
be_emit_char(env, '%');
return s + 1;
case 'w':
case 'b':
modifier = c;
++s;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
break;
default:
ir_fprintf(stderr, "Warning: asm text (%+F) contains unknown modifier "
"'%c' for asm op\n", node, c);
++s;
break;
}
/* parse number */
sscanf(s, "%d%n", &num, &p);
if(num < 0) {
ir_fprintf(stderr, "Warning: Couldn't parse assembler operand (%+F)\n",
node);
return s;
} else {
s += p;
}
/* get register */
attr = get_ia32_attr(node);
n_outs = attr->data.n_res;
if(num < n_outs) {
reg = get_out_reg(env, node, num);
} else {
int in = num - n_outs;
if(in >= get_irn_arity(node)) {
ir_fprintf(stderr, "Warning: Invalid input %d specified in asm "
"op (%+F)\n", num, node);
return s;
}
reg = get_in_reg(env, node, in);
}
if(reg == NULL) {
ir_fprintf(stderr, "Warning: no register assigned for %d asm op "
"(%+F)\n", num, node);
return s;
}
/* emit it */
be_emit_char(env, '%');
switch(modifier) {
case 0:
reg_name = arch_register_get_name(reg);
break;
case 'b':
reg_name = ia32_get_mapped_reg_name(env->isa->regs_8bit, reg);
break;
case 'w':
reg_name = ia32_get_mapped_reg_name(env->isa->regs_16bit, reg);
break;
default:
panic("Invalid asm op modifier");
}
be_emit_string(env, reg_name);
return s;
}
/** /**
* Emits code for an ASM pseudo op. * Emits code for an ASM pseudo op.
*/ */
static static
void emit_ASM(ia32_emit_env_t *env, const ir_node *node) { void emit_ia32_Asm(ia32_emit_env_t *env, const ir_node *node)
/* for now, really simple */ {
const char *s = get_ASM_text(node); ia32_attr_t *attr = get_ia32_attr(node);
ident *asm_text = attr->cnst_val.asm_text;
const char *s = get_id_str(asm_text);
if (s[0] != '\t') be_emit_cstring(env, "# Begin ASM \t");
be_emit_cstring(env, "\t");
be_emit_string(env, s);
be_emit_finish_line_gas(env, node); be_emit_finish_line_gas(env, node);
if (s[0] != '\t')
be_emit_char(env, '\t');
while(*s != 0) {
if(*s == '%') {
s = emit_asm_operand(env, node, s);
continue;
} else {
be_emit_char(env, *s);
}
++s;
}
be_emit_char(env, '\n');
be_emit_write_line(env);
be_emit_cstring(env, "# End ASM\n");
be_emit_write_line(env);
} }
/********************************** /**********************************
...@@ -1788,6 +1905,7 @@ void ia32_register_emitters(void) { ...@@ -1788,6 +1905,7 @@ void ia32_register_emitters(void) {
ia32_register_spec_emitters(); ia32_register_spec_emitters();
/* other ia32 emitter functions */ /* other ia32 emitter functions */
IA32_EMIT(Asm);
IA32_EMIT(CondJmp); IA32_EMIT(CondJmp);
IA32_EMIT(TestJmp); IA32_EMIT(TestJmp);
IA32_EMIT(CJmp); IA32_EMIT(CJmp);
...@@ -1832,7 +1950,6 @@ void ia32_register_emitters(void) { ...@@ -1832,7 +1950,6 @@ void ia32_register_emitters(void) {
/* firm emitter */ /* firm emitter */
EMIT(Jmp); EMIT(Jmp);
EMIT(ASM);
IGN(Proj); IGN(Proj);
IGN(Phi); IGN(Phi);
IGN(Start); IGN(Start);
......
...@@ -121,6 +121,7 @@ struct ia32_attr_t { ...@@ -121,6 +121,7 @@ struct ia32_attr_t {
union { union {
tarval *tv; /**< tarval for immediate operations */ tarval *tv; /**< tarval for immediate operations */
ir_entity *sc; /**< the symconst ident */ ir_entity *sc; /**< the symconst ident */
ident *asm_text; /**< used by asm node */
} cnst_val; } cnst_val;
ir_mode *ls_mode; /**< Load/Store mode: This is the mode of the value ir_mode *ls_mode; /**< Load/Store mode: This is the mode of the value
......
...@@ -2392,7 +2392,71 @@ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *node) { ...@@ -2392,7 +2392,71 @@ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *node) {
return res; return res;
} }
static
ir_node *gen_ASM(ia32_transform_env_t *env, ir_node *node)
{
int i, arity;
ir_graph *irg = env->irg;
ir_node *block = transform_node(env, get_nodes_block(node));
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node **in;
ir_node *res;
int out_arity;
ia32_attr_t *attr;
const arch_register_req_t **out_reqs;
const arch_register_req_t **in_reqs;
struct obstack *obst;
/* assembler could contain float statements */
FP_USED(env->cg);
/* transform inputs */
arity = get_irn_arity(node);
in = alloca(arity * sizeof(in[0]));
for(i = 0; i < arity; ++i) {
ir_node *pred = get_irn_n(node, i);
ir_node *transformed = transform_node(env, pred);
in[i] = transformed;
}
out_arity = get_ASM_n_output_constraints(node) + get_ASM_n_clobbers(node);
res = new_rd_ia32_Asm(dbgi, irg, block, arity, in, out_arity);
/* construct register constraints */
obst = get_irg_obstack(irg);
out_reqs = obstack_alloc(obst, out_arity * sizeof(out_reqs[0]));
for(i = 0; i < out_arity; ++i) {
arch_register_req_t *req = obstack_alloc(obst, sizeof(req[0]));
memset(req, 0, sizeof(req[0]));
/* TODO: parse constraints */
req->type = arch_register_req_type_normal;
req->cls = &ia32_reg_classes[CLASS_ia32_gp];
out_reqs[i] = req;
}
set_ia32_out_req_all(res, out_reqs);
in_reqs = obstack_alloc(obst, arity * sizeof(in_reqs[0]));
for(i = 0; i < arity; ++i) {
arch_register_req_t *req = obstack_alloc(obst, sizeof(req[0]));
memset(req, 0, sizeof(req[0]));
/* TODO: parse constraints */
req->type = arch_register_req_type_normal;
req->cls = &ia32_reg_classes[CLASS_ia32_gp];
in_reqs[i] = req;
}
set_ia32_in_req_all(res, in_reqs);
attr = get_ia32_attr(res);
attr->cnst_val.asm_text = get_ASM_text(node);
SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, node));
return res;
}
/******************************************** /********************************************
* _ _ * _ _
...@@ -3703,6 +3767,7 @@ static void register_transformers(void) { ...@@ -3703,6 +3767,7 @@ static void register_transformers(void) {
GEN(Store); GEN(Store);
GEN(Cond); GEN(Cond);
GEN(ASM);
GEN(CopyB); GEN(CopyB);
//GEN(Mux); //GEN(Mux);
BAD(Mux); BAD(Mux);
......
double test(double angle) { #include <stdio.h>
double result;
asm ("fsinx %1,%0" : "=f" (result) : "f" (angle)); static inline unsigned char inb(const unsigned short port)
return result; {
unsigned char val;
__asm__ __volatile__ ("inb %w1, %0" : "=a"(val) : "dN"(port));
return val;
}
static inline void outb(const unsigned short port, const unsigned char val)
{
int k = val; /* just here to test the b modifier in %b0 */
__asm__ __volatile__ ("outb %b0, %1" : : "a"(k), "dN"(port));
}
static void sincostest(double arg)
{
double cos, sin;
__asm__ ("fsincos" : "=t"(cos), "=u"(sin) : "0" (arg));
printf("Arg: %f Sin: %f Cos: %f\n", arg, sin, cos);
} }
int main(int argc, char *argv[]) { static inline int mov(int val)
printf("%f\n", test(0.5)); {
int res;
__asm__ ("movl %0, %1" : "=r"(res) : "ri" (val));
return res;
}
int main()
{
//sincostest(0.5);
//outb(123, 42);
return mov(0);
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment