summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCamil Staps2016-12-01 15:30:53 +0000
committerCamil Staps2016-12-01 15:30:53 +0000
commita355a7aaf66179b3ba788010fbb31431caecb6b4 (patch)
tree7fb57767cebb44006828813bed189c1d283eab66
parentNow really fix offsets (diff)
Don't generate illegal immediate constants
-rw-r--r--cgthumb2was.c28
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);