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) {
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);
......
......@@ -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
......
......@@ -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);
......
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);
}
Markdown is supported
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