more work on ia32 assembler nodes
authorMatthias Braun <matze@braunis.de>
Sat, 2 Jun 2007 16:49:17 +0000 (16:49 +0000)
committerMatthias Braun <matze@braunis.de>
Sat, 2 Jun 2007 16:49:17 +0000 (16:49 +0000)
[r14270]

ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_nodes_attr.h
ir/be/ia32/ia32_transform.c
ir/be/test/asm_test.c

index c9d1f74..9986a80 100644 (file)
@@ -1311,18 +1311,135 @@ void emit_Jmp(ia32_emit_env_t *env, const ir_node *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.
  */
 static
-void emit_ASM(ia32_emit_env_t *env, const ir_node *node) {
-       /* for now, really simple */
-       const char *s = get_ASM_text(node);
+void emit_ia32_Asm(ia32_emit_env_t *env, const ir_node *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, "\t");
-       be_emit_string(env, s);
+       be_emit_cstring(env, "# Begin ASM \t");
        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) {
        ia32_register_spec_emitters();
 
        /* other ia32 emitter functions */
+       IA32_EMIT(Asm);
        IA32_EMIT(CondJmp);
        IA32_EMIT(TestJmp);
        IA32_EMIT(CJmp);
@@ -1832,7 +1950,6 @@ void ia32_register_emitters(void) {
 
        /* firm emitter */
        EMIT(Jmp);
-       EMIT(ASM);
        IGN(Proj);
        IGN(Phi);
        IGN(Start);
index 3ef45f2..1e8b026 100644 (file)
@@ -121,6 +121,7 @@ struct ia32_attr_t {
        union {
                tarval    *tv;        /**< tarval for immediate operations */
                ir_entity *sc;        /**< the symconst ident */
+               ident     *asm_text;  /**< used by asm node */
        } cnst_val;
 
        ir_mode *ls_mode;     /**< Load/Store mode: This is the mode of the value
index 3d1a368..97268ff 100644 (file)
@@ -2392,7 +2392,71 @@ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *node) {
        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) {
        GEN(Store);
        GEN(Cond);
 
+       GEN(ASM);
        GEN(CopyB);
        //GEN(Mux);
        BAD(Mux);
index 6c8a4c7..d6c3696 100644 (file)
@@ -1,9 +1,42 @@
-double test(double angle) {
-       double result;
-       asm ("fsinx %1,%0" : "=f" (result) : "f" (angle));
-       return result;
+#include <stdio.h>
+
+static inline unsigned char inb(const unsigned short port)
+{
+    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[]) {
-       printf("%f\n", test(0.5));
+static inline int mov(int val)
+{
+       int res;
+
+       __asm__ ("movl %0, %1" : "=r"(res) : "ri" (val));
+
+       return res;
+}
+
+
+int main()
+{
+       //sincostest(0.5);
+       //outb(123, 42);
+
+       return mov(0);
 }