+static
+ir_node *try_create_Immediate(ia32_transform_env_t *env, ir_node *node,
+ unsigned immediate_max)
+{
+ int minus = 0;
+ tarval *offset = NULL;
+ int offset_sign = 0;
+ ir_entity *symconst_ent = NULL;
+ int symconst_sign = 0;
+ ir_mode *mode;
+ ir_node *cnst = NULL;
+ ir_node *symconst = NULL;
+ ir_node *res;
+ ir_graph *irg;
+ dbg_info *dbgi;
+ ir_node *block;
+ ia32_attr_t *attr;
+
+ mode = get_irn_mode(node);
+ if(!mode_is_int(mode) && !mode_is_character(mode) &&
+ !mode_is_reference(mode)) {
+ return NULL;
+ }
+
+ if(is_Minus(node)) {
+ minus = 1;
+ node = get_Minus_op(node);
+ }
+
+ if(is_Const(node)) {
+ cnst = node;
+ symconst = NULL;
+ offset_sign = minus;
+ } else if(is_SymConst(node)) {
+ cnst = NULL;
+ symconst = node;
+ symconst_sign = minus;
+ } else if(is_Add(node)) {
+ ir_node *left = get_Add_left(node);
+ ir_node *right = get_Add_right(node);
+ if(is_Const(left) && is_SymConst(right)) {
+ cnst = left;
+ symconst = right;
+ symconst_sign = minus;
+ offset_sign = minus;
+ } else if(is_SymConst(left) && is_Const(right)) {
+ cnst = right;
+ symconst = left;
+ symconst_sign = minus;
+ offset_sign = minus;
+ }
+ } else if(is_Sub(node)) {
+ ir_node *left = get_Add_left(node);
+ ir_node *right = get_Add_right(node);
+ if(is_Const(left) && is_SymConst(right)) {
+ cnst = left;
+ symconst = right;
+ symconst_sign = !minus;
+ offset_sign = minus;
+ } else if(is_SymConst(left) && is_Const(right)) {
+ cnst = right;
+ symconst = left;
+ symconst_sign = minus;
+ offset_sign = !minus;
+ }
+ } else {
+ return NULL;
+ }
+
+ if(cnst != NULL) {
+ tarval *tv;
+ tarval *tvu;
+ long val;
+
+ tv = get_Const_tarval(cnst);
+ if(!tarval_is_long(tv)) {
+ ir_fprintf(stderr, "Optimisation Warning: tarval from %+F is not a "
+ "long?\n", cnst);
+ return NULL;
+ }
+
+ tvu = tarval_convert_to(tv, mode_Iu);
+ val = get_tarval_long(tvu);
+ if(val > immediate_max)
+ return NULL;
+
+ offset = tvu;
+ }
+ if(symconst != NULL) {
+ if(immediate_max != 0xffffffff) {
+ /* we need full 32bits for symconsts */
+ return NULL;
+ }
+
+ if(get_SymConst_kind(symconst) != symconst_addr_ent)
+ return NULL;
+ symconst_ent = get_SymConst_entity(symconst);
+ }
+
+ irg = env->irg;
+ dbgi = get_irn_dbg_info(node);
+ block = get_irg_start_block(irg);
+ res = new_rd_ia32_Immediate(dbgi, irg, block);
+ arch_set_irn_register(env->cg->arch_env, res, &ia32_gp_regs[REG_GP_NOREG]);
+
+ /* make sure we don't schedule stuff before the barrier */
+ add_irn_dep(res, get_irg_frame(irg));
+
+ /* misuse some fields for now... */
+ attr = get_ia32_attr(res);
+ attr->am_sc = symconst_ent;
+ attr->data.am_sc_sign = symconst_sign;
+ if(offset_sign && offset != NULL) {
+ offset = tarval_neg(offset);
+ }
+ attr->cnst_val.tv = offset;
+ attr->data.imm_tp = ia32_ImmConst;
+
+ return res;
+}
+
+typedef struct constraint_t constraint_t;
+struct constraint_t {
+ const arch_register_req_t *req;
+ unsigned immediate_possible;
+ unsigned immediate_max;
+};
+
+static
+void parse_asm_constraint(ia32_transform_env_t *env, ir_node *node,
+ constraint_t *constraint, const char *c, int is_in)
+{
+ int immediate_possible = 0;
+ unsigned immediate_max = 0xffffffff;
+ unsigned limited = 0;
+ const arch_register_class_t *cls = NULL;
+ ir_graph *irg;
+ struct obstack *obst;
+ arch_register_req_t *req;
+ unsigned *limited_ptr;
+
+ printf("Constraint: %s\n", c);
+
+ while(*c != 0) {
+ switch(*c) {
+ case ' ':
+ case '\t':
+ case '\n':
+ break;
+
+ case 'a':
+ assert(cls == NULL ||
+ (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ limited |= 1 << REG_EAX;
+ break;
+ case 'b':
+ assert(cls == NULL ||
+ (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ limited |= 1 << REG_EBX;
+ break;
+ case 'c':
+ assert(cls == NULL ||
+ (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ limited |= 1 << REG_ECX;
+ break;
+ case 'd':
+ assert(cls == NULL ||
+ (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ limited |= 1 << REG_EDX;
+ break;
+ case 'D':
+ assert(cls == NULL ||
+ (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ limited |= 1 << REG_EDI;
+ break;
+ case 'S':
+ assert(cls == NULL ||
+ (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ limited |= 1 << REG_ESI;
+ break;
+
+ case 'R':
+ case 'r':
+ case 'p':
+ assert(cls == NULL);
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ break;
+
+ case 'f':
+ case 't':
+ case 'u':
+ assert(cls == NULL);
+ cls = &ia32_reg_classes[CLASS_ia32_vfp];
+ break;
+
+ case 'x':
+ assert(cls == NULL);
+ cls = &ia32_reg_classes[CLASS_ia32_xmm];
+ break;
+
+ case 'I':
+ assert(!immediate_possible);
+ immediate_possible = 1;
+ immediate_max = 31;
+ break;
+ case 'J':
+ assert(!immediate_possible);
+ immediate_possible = 1;
+ immediate_max = 63;
+ break;
+ case 'n':
+ case 'i':
+ assert(!immediate_possible);
+ immediate_possible = 1;
+ break;
+ case 'M':
+ assert(!immediate_possible);
+ immediate_possible = 1;
+ immediate_max = 3;
+ break;
+ case 'N':
+ assert(!immediate_possible);
+ immediate_possible = 1;
+ immediate_max = 0xff;
+ break;
+
+ case 'g':
+ assert(!immediate_possible && cls == NULL);
+ immediate_possible = 1;
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* TODO */
+ assert(0 && "other_same not implemented yet");
+ break;
+
+ case 'E': /* no float consts yet */
+ case 'F': /* no float consts yet */
+ case 's': /* makes no sense on x86 */
+ case 'X': /* we can't support that in firm */
+ case 'm':
+ case 'o':
+ case 'V':
+ case '<': /* no autodecrement on x86 */
+ case '>': /* no autoincrement on x86 */
+ case 'C': /* sse constant not supported yet */
+ case 'G': /* 80387 constant not supported yet */
+ case 'y': /* we don't support mmx registers yet */
+ case 'Z': /* not available in 32 bit mode */
+ case 'e': /* not available in 32 bit mode */
+ case 'K': /* gcc docu is cryptic */
+ case 'L': /* gcc docu is cryptic */
+ assert(0);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ ++c;
+ }
+
+ if(immediate_possible && cls == NULL) {
+ cls = &ia32_reg_classes[CLASS_ia32_gp];
+ }
+ assert(!immediate_possible || cls == &ia32_reg_classes[CLASS_ia32_gp]);
+ assert(cls != NULL);
+
+ if(immediate_possible) {
+ assert(is_in && "imeediates make no sense for output constraints");
+ printf("Immediate possible 0-%x\n", immediate_max);
+ }
+ /* todo: check types (no float input on 'r' constrainted in and such... */
+
+ irg = env->irg;
+ obst = get_irg_obstack(irg);
+
+ if(limited != 0) {
+ req = obstack_alloc(obst, sizeof(req[0]) + sizeof(unsigned));
+ limited_ptr = (unsigned*) (req+1);
+ } else {
+ req = obstack_alloc(obst, sizeof(req[0]));
+ }
+ memset(req, 0, sizeof(req[0]));
+
+ if(limited != 0) {
+ req->type = arch_register_req_type_limited;
+ *limited_ptr = limited;
+ req->limited = limited_ptr;
+ } else {
+ req->type = arch_register_req_type_normal;
+ }
+ req->cls = cls;
+
+ constraint->req = req;
+ constraint->immediate_possible = immediate_possible;
+ constraint->immediate_max = immediate_max;
+}
+