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);
}
/**********************************
ia32_register_spec_emitters();
/* other ia32 emitter functions */
+ IA32_EMIT(Asm);
IA32_EMIT(CondJmp);
IA32_EMIT(TestJmp);
IA32_EMIT(CJmp);
/* firm emitter */
EMIT(Jmp);
- EMIT(ASM);
IGN(Proj);
IGN(Phi);
IGN(Start);
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
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;
+}
/********************************************
* _ _
GEN(Store);
GEN(Cond);
+ GEN(ASM);
GEN(CopyB);
//GEN(Mux);
BAD(Mux);
-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);
}