/* -- asm.c */
/* Handle register lists for LDMx and STMx */
+static int
+parse_register_number (strp)
+ const char **strp;
+{
+ int regno;
+ if (**strp < '0' || **strp > '9')
+ return -1; /* error */
+ regno = **strp - '0';
+ ++*strp;
+
+ if (**strp >= '0' && **strp <= '9')
+ {
+ regno = regno * 10 + (**strp - '0');
+ ++*strp;
+ }
+
+ return regno;
+}
+
static const char *
-parse_low_register_list (od, strp, opindex, valuep)
+parse_register_list (od, strp, opindex, valuep, high_low, load_store)
CGEN_OPCODE_DESC od;
const char **strp;
int opindex;
unsigned long *valuep;
+ int high_low; /* 0 == high, 1 == low */
+ int load_store; /* 0 == load, 1 == store */
{
+ int regno;
*valuep = 0;
while (**strp && **strp != ')')
{
+ if (**strp != 'R' && **strp != 'r')
+ break;
++*strp;
+
+ regno = parse_register_number (strp);
+ if (regno == -1)
+ return "Register number is not valid";
+ if (regno > 7 && !high_low)
+ return "Register must be between r0 and r7";
+ if (regno < 8 && high_low)
+ return "Register must be between r8 and r15";
+
+ if (high_low)
+ regno -= 8;
+
+ if (load_store) /* mask is reversed for store */
+ *valuep |= 0x80 >> regno;
+ else
+ *valuep |= 1 << regno;
+
+ if (**strp == ',')
+ {
+ if (*(*strp + 1) == ')')
+ break;
+ ++*strp;
+ }
}
- if (!*strp)
+ if (!*strp || **strp != ')')
return "Register list is not valid";
return NULL;
}
static const char *
-parse_hi_register_list (od, strp, opindex, valuep)
+parse_low_register_list_ld (od, strp, opindex, valuep)
+ CGEN_OPCODE_DESC od;
+ const char **strp;
+ int opindex;
+ unsigned long *valuep;
+{
+ return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 0/*load*/);
+}
+
+static const char *
+parse_hi_register_list_ld (od, strp, opindex, valuep)
+ CGEN_OPCODE_DESC od;
+ const char **strp;
+ int opindex;
+ unsigned long *valuep;
+{
+ return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 0/*load*/);
+}
+
+static const char *
+parse_low_register_list_st (od, strp, opindex, valuep)
+ CGEN_OPCODE_DESC od;
+ const char **strp;
+ int opindex;
+ unsigned long *valuep;
+{
+ return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 1/*store*/);
+}
+
+static const char *
+parse_hi_register_list_st (od, strp, opindex, valuep)
CGEN_OPCODE_DESC od;
const char **strp;
int opindex;
unsigned long *valuep;
{
- return parse_low_register_list (od, strp, opindex, valuep);
+ return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 1/*store*/);
}
/* -- */
case FR30_OPERAND_U4C :
errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4C, &fields->f_u4c);
break;
- case FR30_OPERAND_M4 :
- errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
- break;
case FR30_OPERAND_U8 :
errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U8, &fields->f_u8);
break;
case FR30_OPERAND_I32 :
errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I32, &fields->f_i32);
break;
+ case FR30_OPERAND_M4 :
+ errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
+ break;
case FR30_OPERAND_I20 :
errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I20, &fields->f_i20);
break;
- case FR30_OPERAND_LABEL9 :
- {
- bfd_vma value;
- errmsg = cgen_parse_address (od, strp, FR30_OPERAND_LABEL9, 0, NULL, & value);
- fields->f_rel9 = value;
- }
- break;
case FR30_OPERAND_DIR8 :
errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR8, &fields->f_dir8);
break;
case FR30_OPERAND_DIR10 :
errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR10, &fields->f_dir10);
break;
+ case FR30_OPERAND_LABEL9 :
+ {
+ bfd_vma value;
+ errmsg = cgen_parse_address (od, strp, FR30_OPERAND_LABEL9, 0, NULL, & value);
+ fields->f_rel9 = value;
+ }
+ break;
case FR30_OPERAND_LABEL12 :
{
bfd_vma value;
fields->f_rel12 = value;
}
break;
- case FR30_OPERAND_REGLIST_LOW :
- errmsg = parse_low_register_list (od, strp, FR30_OPERAND_REGLIST_LOW, &fields->f_reglist_low);
+ case FR30_OPERAND_REGLIST_LOW_LD :
+ errmsg = parse_low_register_list_ld (od, strp, FR30_OPERAND_REGLIST_LOW_LD, &fields->f_reglist_low_ld);
break;
- case FR30_OPERAND_REGLIST_HI :
- errmsg = parse_hi_register_list (od, strp, FR30_OPERAND_REGLIST_HI, &fields->f_reglist_hi);
+ case FR30_OPERAND_REGLIST_HI_LD :
+ errmsg = parse_hi_register_list_ld (od, strp, FR30_OPERAND_REGLIST_HI_LD, &fields->f_reglist_hi_ld);
+ break;
+ case FR30_OPERAND_REGLIST_LOW_ST :
+ errmsg = parse_low_register_list_st (od, strp, FR30_OPERAND_REGLIST_LOW_ST, &fields->f_reglist_low_st);
+ break;
+ case FR30_OPERAND_REGLIST_HI_ST :
+ errmsg = parse_hi_register_list_st (od, strp, FR30_OPERAND_REGLIST_HI_ST, &fields->f_reglist_hi_st);
break;
case FR30_OPERAND_CC :
errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_CC, &fields->f_cc);
case FR30_OPERAND_U4C :
errmsg = insert_normal (od, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, buffer);
break;
- case FR30_OPERAND_M4 :
- {
- long value = fields->f_m4;
- value = ((value) & (15));
- errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
- }
- break;
case FR30_OPERAND_U8 :
errmsg = insert_normal (od, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
break;
}
break;
case FR30_OPERAND_DISP8 :
- errmsg = insert_normal (od, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, buffer);
+ errmsg = insert_normal (od, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
break;
case FR30_OPERAND_DISP9 :
{
long value = fields->f_disp9;
value = ((int) (value) >> (1));
- errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, buffer);
+ errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
}
break;
case FR30_OPERAND_DISP10 :
{
long value = fields->f_disp10;
value = ((int) (value) >> (2));
- errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, buffer);
+ errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
}
break;
case FR30_OPERAND_S10 :
{
long value = fields->f_s10;
value = ((int) (value) >> (2));
- errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 8, 8, 16, total_length, buffer);
+ errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 8, 8, 16, total_length, buffer);
}
break;
case FR30_OPERAND_U10 :
case FR30_OPERAND_I32 :
errmsg = insert_normal (od, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 0, 32, 32, total_length, buffer);
break;
+ case FR30_OPERAND_M4 :
+ {
+ long value = fields->f_m4;
+ value = ((value) & (15));
+ errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
+ }
+ break;
case FR30_OPERAND_I20 :
{
do {
break;
}
break;
- case FR30_OPERAND_LABEL9 :
- {
- long value = fields->f_rel9;
- value = ((int) (((value) - (((pc) + (2))))) >> (1));
- errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 0, 8, 8, 16, total_length, buffer);
- }
- break;
case FR30_OPERAND_DIR8 :
errmsg = insert_normal (od, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
break;
errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
}
break;
+ case FR30_OPERAND_LABEL9 :
+ {
+ long value = fields->f_rel9;
+ value = ((int) (((value) - (((pc) + (2))))) >> (1));
+ errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 8, 8, 16, total_length, buffer);
+ }
+ break;
case FR30_OPERAND_LABEL12 :
{
long value = fields->f_rel12;
- value = ((int) (((value) - (((pc) & (-2))))) >> (1));
- errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 0, 5, 11, 16, total_length, buffer);
+ value = ((int) (((value) - (((pc) + (2))))) >> (1));
+ errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 5, 11, 16, total_length, buffer);
}
break;
- case FR30_OPERAND_REGLIST_LOW :
- errmsg = insert_normal (od, fields->f_reglist_low, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+ case FR30_OPERAND_REGLIST_LOW_LD :
+ errmsg = insert_normal (od, fields->f_reglist_low_ld, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+ break;
+ case FR30_OPERAND_REGLIST_HI_LD :
+ errmsg = insert_normal (od, fields->f_reglist_hi_ld, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+ break;
+ case FR30_OPERAND_REGLIST_LOW_ST :
+ errmsg = insert_normal (od, fields->f_reglist_low_st, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
break;
- case FR30_OPERAND_REGLIST_HI :
- errmsg = insert_normal (od, fields->f_reglist_hi, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
+ case FR30_OPERAND_REGLIST_HI_ST :
+ errmsg = insert_normal (od, fields->f_reglist_hi_st, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
break;
case FR30_OPERAND_CC :
errmsg = insert_normal (od, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 16, total_length, buffer);
#endif
/* Ensure VALUE will fit. */
- if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
+ if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
{
unsigned long maxval = mask;
if ((unsigned long) value > maxval)