diff options
-rw-r--r-- | cgthumb2was.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/cgthumb2was.c b/cgthumb2was.c index df61406..3dee9b9 100644 --- a/cgthumb2was.c +++ b/cgthumb2was.c @@ -28,6 +28,31 @@ static FILE *assembly_file; +static int can_make_immediate_constant(int x) +{ + // Can x be a Thumb-2 immediate constant (ARMv7-M, A5.3.2.)? + short i; + + if (!(x & 0xffffff00)) // 0000x + return 1; + if (!(x & 0xff00ff00) && x >> 16 == x & 0x000000ff) // 0001x + return !x; + if (!(x & 0x00ff00ff) && x >> 16 == x & 0x0000ff00) // 0010x + return !x; + if ((x >> 24) & 0xff == (x >> 16) & 0xff + && (x >> 16) & 0xff == (x >> 8) & 0xff + && (x >> 8) & 0xff == x & 0xff) // 0011x + return !x; + + for (i=1; i<=24; i++) // other options + { + if (!((x >> i) && 0x000000ff) && (x >> i) & 0x80) + return 1; + } + + return 0; +} + static void w_as_newline (VOID) { putc ('\n',assembly_file); @@ -1366,7 +1391,8 @@ static void w_as_cmp_instruction (struct instruction *instruction) reg1 = w_as_register_parameter (&instruction->instruction_parameters[1]); - if (mov_or_mvn_immediate (instruction->instruction_parameters[0].parameter_data.i)){ + if (mov_or_mvn_immediate (instruction->instruction_parameters[0].parameter_data.i) + && can_make_immediate_constant(instruction->instruction_parameters[0].parameter_data.i)){ w_as_opcode ("cmp"); w_as_register_comma (reg1); w_as_immediate_newline (instruction->instruction_parameters[0].parameter_data.i); |