Home | History | Annotate | Download | only in disassembler
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 #include <stdio.h>
     29 #include <inttypes.h>
     30 #include <string.h>
     31 
     32 int arm64_disassemble(uint32_t code, char* instr);
     33 
     34 struct test_table_entry_t
     35 {
     36      uint32_t code;
     37      const char *instr;
     38 };
     39 static test_table_entry_t test_table [] =
     40 {
     41     { 0x91000240, "add x0, x18, #0x0, lsl #0"         },
     42     { 0x9140041f, "add sp, x0, #0x1, lsl #12"         },
     43     { 0x917ffff2, "add x18, sp, #0xfff, lsl #12"      },
     44 
     45     { 0xd13ffe40, "sub x0, x18, #0xfff, lsl #0"       },
     46     { 0xd140001f, "sub sp, x0, #0x0, lsl #12"         },
     47     { 0xd14007f2, "sub x18, sp, #0x1, lsl #12"        },
     48 
     49     { 0x8b1e0200, "add x0, x16, x30, lsl #0"          },
     50     { 0x8b507fdf, "add xzr, x30, x16, lsr #31"        },
     51     { 0x8b8043f0, "add x16, xzr, x0, asr #16"         },
     52     { 0x8b5f401e, "add x30, x0, xzr, lsr #16"         },
     53 
     54 
     55     { 0x4b1e0200, "sub w0, w16, w30, lsl #0"          },
     56     { 0x4b507fdf, "sub wzr, w30, w16, lsr #31"        },
     57     { 0x4b8043f0, "sub w16, wzr, w0, asr #16"         },
     58     { 0x4b5f401e, "sub w30, w0, wzr, lsr #16"         },
     59 
     60     { 0x6b1e0200, "subs w0, w16, w30, lsl #0"         },
     61     { 0x6b507fdf, "subs wzr, w30, w16, lsr #31"       },
     62     { 0x6b8043f0, "subs w16, wzr, w0, asr #16"        },
     63     { 0x6b5f401e, "subs w30, w0, wzr, lsr #16"        },
     64 
     65     { 0x0a1e0200, "and w0, w16, w30, lsl #0"          },
     66     { 0x0a507fdf, "and wzr, w30, w16, lsr #31"        },
     67     { 0x0a8043f0, "and w16, wzr, w0, asr #16"         },
     68     { 0x0adf401e, "and w30, w0, wzr, ror #16"         },
     69 
     70     { 0x2a1e0200, "orr w0, w16, w30, lsl #0"          },
     71     { 0x2a507fdf, "orr wzr, w30, w16, lsr #31"        },
     72     { 0x2a8043f0, "orr w16, wzr, w0, asr #16"         },
     73     { 0x2adf401e, "orr w30, w0, wzr, ror #16"         },
     74 
     75     { 0x2a3e0200, "orn w0, w16, w30, lsl #0"          },
     76     { 0x2a707fdf, "orn wzr, w30, w16, lsr #31"        },
     77     { 0x2aa043f0, "orn w16, wzr, w0, asr #16"         },
     78     { 0x2aff401e, "orn w30, w0, wzr, ror #16"         },
     79 
     80     { 0x729fffe0, "movk w0, #0xffff, lsl #0"          },
     81     { 0x72a0000f, "movk w15, #0x0, lsl #16"           },
     82     { 0x7281fffe, "movk w30, #0xfff, lsl #0"          },
     83     { 0x72a0003f, "movk wzr, #0x1, lsl #16"           },
     84 
     85     { 0x529fffe0, "movz w0, #0xffff, lsl #0"          },
     86     { 0x52a0000f, "movz w15, #0x0, lsl #16"           },
     87     { 0x5281fffe, "movz w30, #0xfff, lsl #0"          },
     88     { 0x52a0003f, "movz wzr, #0x1, lsl #16"           },
     89 
     90     { 0xd29fffe0, "movz x0, #0xffff, lsl #0"          },
     91     { 0xd2a0000f, "movz x15, #0x0, lsl #16"           },
     92     { 0xd2c1fffe, "movz x30, #0xfff, lsl #32"         },
     93     { 0xd2e0003f, "movz xzr, #0x1, lsl #48"           },
     94 
     95     { 0x1a8003e0, "csel w0, wzr, w0, eq"              },
     96     { 0x1a831001, "csel w1, w0, w3, ne"               },
     97     { 0x1a9e2022, "csel w2, w1, w30, cs"              },
     98     { 0x1a8a3083, "csel w3, w4, w10, cc"              },
     99     { 0x1a8b40e4, "csel w4, w7, w11, mi"              },
    100     { 0x1a9b5105, "csel w5, w8, w27, pl"              },
    101     { 0x1a846167, "csel w7, w11, w4, vs"              },
    102     { 0x1a8671c8, "csel w8, w14, w6, vc"              },
    103     { 0x1a878289, "csel w9, w20, w7, hi"              },
    104     { 0x1a8c92aa, "csel w10, w21, w12, ls"            },
    105     { 0x1a8ea2ce, "csel w14, w22, w14, ge"            },
    106     { 0x1a9fb3b2, "csel w18, w29, wzr, lt"            },
    107     { 0x1a9fc3d8, "csel w24, w30, wzr, gt"            },
    108     { 0x1a82d17e, "csel w30, w11, w2, le"             },
    109     { 0x1a81e19f, "csel wzr, w12, w1, al"             },
    110 
    111     { 0x9a8003e0, "csel x0, xzr, x0, eq"              },
    112     { 0x9a831001, "csel x1, x0, x3, ne"               },
    113     { 0x9a9e2022, "csel x2, x1, x30, cs"              },
    114     { 0x9a8a3083, "csel x3, x4, x10, cc"              },
    115     { 0x9a8b40e4, "csel x4, x7, x11, mi"              },
    116     { 0x9a9b5105, "csel x5, x8, x27, pl"              },
    117     { 0x9a846167, "csel x7, x11, x4, vs"              },
    118     { 0x9a8671c8, "csel x8, x14, x6, vc"              },
    119     { 0x9a878289, "csel x9, x20, x7, hi"              },
    120     { 0x9a8c92aa, "csel x10, x21, x12, ls"            },
    121     { 0x9a8ea2ce, "csel x14, x22, x14, ge"            },
    122     { 0x9a9fb3b2, "csel x18, x29, xzr, lt"            },
    123     { 0x9a9fc3d8, "csel x24, x30, xzr, gt"            },
    124     { 0x9a82d17e, "csel x30, x11, x2, le"             },
    125     { 0x9a81e19f, "csel xzr, x12, x1, al"             },
    126 
    127     { 0x5a8003e0, "csinv w0, wzr, w0, eq"             },
    128     { 0x5a831001, "csinv w1, w0, w3, ne"              },
    129     { 0x5a9e2022, "csinv w2, w1, w30, cs"             },
    130     { 0x5a8a3083, "csinv w3, w4, w10, cc"             },
    131     { 0x5a8b40e4, "csinv w4, w7, w11, mi"             },
    132     { 0x5a9b5105, "csinv w5, w8, w27, pl"             },
    133     { 0x5a846167, "csinv w7, w11, w4, vs"             },
    134     { 0x5a8671c8, "csinv w8, w14, w6, vc"             },
    135     { 0x5a878289, "csinv w9, w20, w7, hi"             },
    136     { 0x5a8c92aa, "csinv w10, w21, w12, ls"           },
    137     { 0x5a8ea2ce, "csinv w14, w22, w14, ge"           },
    138     { 0x5a9fb3b2, "csinv w18, w29, wzr, lt"           },
    139     { 0x5a9fc3d8, "csinv w24, w30, wzr, gt"           },
    140     { 0x5a82d17e, "csinv w30, w11, w2, le"            },
    141     { 0x5a81e19f, "csinv wzr, w12, w1, al"            },
    142 
    143     { 0x1b1f3fc0, "madd w0, w30, wzr, w15"            },
    144     { 0x1b0079ef, "madd w15, w15, w0, w30"            },
    145     { 0x1b0f7ffe, "madd w30, wzr, w15, wzr"           },
    146     { 0x1b1e001f, "madd wzr, w0, w30, w0"             },
    147 
    148     { 0x9b3f3fc0, "smaddl x0, w30, wzr, x15"          },
    149     { 0x9b2079ef, "smaddl x15, w15, w0, x30"          },
    150     { 0x9b2f7ffe, "smaddl x30, wzr, w15, xzr"         },
    151     { 0x9b3e001f, "smaddl xzr, w0, w30, x0"           },
    152 
    153     { 0xd65f0000, "ret x0"                            },
    154     { 0xd65f01e0, "ret x15"                           },
    155     { 0xd65f03c0, "ret x30"                           },
    156     { 0xd65f03e0, "ret xzr"                           },
    157 
    158     { 0xb87f4be0, "ldr w0, [sp, wzr, uxtw #0]"        },
    159     { 0xb87ed80f, "ldr w15, [x0, w30, sxtw #2]"       },
    160     { 0xb86fc9fe, "ldr w30, [x15, w15, sxtw #0]"      },
    161     { 0xb8605bdf, "ldr wzr, [x30, w0, uxtw #2]"       },
    162     { 0xb87febe0, "ldr w0, [sp, xzr, sxtx #0]"        },
    163     { 0xb87e780f, "ldr w15, [x0, x30, lsl #2]"        },
    164     { 0xb86f69fe, "ldr w30, [x15, x15, lsl #0]"       },
    165     { 0xb860fbdf, "ldr wzr, [x30, x0, sxtx #2]"       },
    166 
    167     { 0xb83f4be0, "str w0, [sp, wzr, uxtw #0]"        },
    168     { 0xb83ed80f, "str w15, [x0, w30, sxtw #2]"       },
    169     { 0xb82fc9fe, "str w30, [x15, w15, sxtw #0]"      },
    170     { 0xb8205bdf, "str wzr, [x30, w0, uxtw #2]"       },
    171     { 0xb83febe0, "str w0, [sp, xzr, sxtx #0]"        },
    172     { 0xb83e780f, "str w15, [x0, x30, lsl #2]"        },
    173     { 0xb82f69fe, "str w30, [x15, x15, lsl #0]"       },
    174     { 0xb820fbdf, "str wzr, [x30, x0, sxtx #2]"       },
    175 
    176     { 0x787f4be0, "ldrh w0, [sp, wzr, uxtw #0]"       },
    177     { 0x787ed80f, "ldrh w15, [x0, w30, sxtw #1]"      },
    178     { 0x786fc9fe, "ldrh w30, [x15, w15, sxtw #0]"     },
    179     { 0x78605bdf, "ldrh wzr, [x30, w0, uxtw #1]"      },
    180     { 0x787febe0, "ldrh w0, [sp, xzr, sxtx #0]"       },
    181     { 0x787e780f, "ldrh w15, [x0, x30, lsl #1]"       },
    182     { 0x786f69fe, "ldrh w30, [x15, x15, lsl #0]"      },
    183     { 0x7860fbdf, "ldrh wzr, [x30, x0, sxtx #1]"      },
    184 
    185     { 0x783f4be0, "strh w0, [sp, wzr, uxtw #0]"       },
    186     { 0x783ed80f, "strh w15, [x0, w30, sxtw #1]"      },
    187     { 0x782fc9fe, "strh w30, [x15, w15, sxtw #0]"     },
    188     { 0x78205bdf, "strh wzr, [x30, w0, uxtw #1]"      },
    189     { 0x783febe0, "strh w0, [sp, xzr, sxtx #0]"       },
    190     { 0x783e780f, "strh w15, [x0, x30, lsl #1]"       },
    191     { 0x782f69fe, "strh w30, [x15, x15, lsl #0]"      },
    192     { 0x7820fbdf, "strh wzr, [x30, x0, sxtx #1]"      },
    193 
    194     { 0x387f5be0, "ldrb w0, [sp, wzr, uxtw #0]"       },
    195     { 0x387ec80f, "ldrb w15, [x0, w30, sxtw ]"        },
    196     { 0x386fd9fe, "ldrb w30, [x15, w15, sxtw #0]"     },
    197     { 0x38604bdf, "ldrb wzr, [x30, w0, uxtw ]"        },
    198     { 0x387ffbe0, "ldrb w0, [sp, xzr, sxtx #0]"       },
    199     { 0x387e780f, "ldrb w15, [x0, x30, lsl #0]"       },
    200     { 0x386f79fe, "ldrb w30, [x15, x15, lsl #0]"      },
    201     { 0x3860ebdf, "ldrb wzr, [x30, x0, sxtx ]"        },
    202 
    203     { 0x383f5be0, "strb w0, [sp, wzr, uxtw #0]"       },
    204     { 0x383ec80f, "strb w15, [x0, w30, sxtw ]"        },
    205     { 0x382fd9fe, "strb w30, [x15, w15, sxtw #0]"     },
    206     { 0x38204bdf, "strb wzr, [x30, w0, uxtw ]"        },
    207     { 0x383ffbe0, "strb w0, [sp, xzr, sxtx #0]"       },
    208     { 0x383e780f, "strb w15, [x0, x30, lsl #0]"       },
    209     { 0x382f79fe, "strb w30, [x15, x15, lsl #0]"      },
    210     { 0x3820ebdf, "strb wzr, [x30, x0, sxtx ]"        },
    211 
    212     { 0xf87f4be0, "ldr x0, [sp, wzr, uxtw #0]"        },
    213     { 0xf87ed80f, "ldr x15, [x0, w30, sxtw #3]"       },
    214     { 0xf86fc9fe, "ldr x30, [x15, w15, sxtw #0]"      },
    215     { 0xf8605bdf, "ldr xzr, [x30, w0, uxtw #3]"       },
    216     { 0xf87febe0, "ldr x0, [sp, xzr, sxtx #0]"        },
    217     { 0xf87e780f, "ldr x15, [x0, x30, lsl #3]"        },
    218     { 0xf86f69fe, "ldr x30, [x15, x15, lsl #0]"       },
    219     { 0xf860fbdf, "ldr xzr, [x30, x0, sxtx #3]"       },
    220 
    221     { 0xf83f4be0, "str x0, [sp, wzr, uxtw #0]"        },
    222     { 0xf83ed80f, "str x15, [x0, w30, sxtw #3]"       },
    223     { 0xf82fc9fe, "str x30, [x15, w15, sxtw #0]"      },
    224     { 0xf8205bdf, "str xzr, [x30, w0, uxtw #3]"       },
    225     { 0xf83febe0, "str x0, [sp, xzr, sxtx #0]"        },
    226     { 0xf83e780f, "str x15, [x0, x30, lsl #3]"        },
    227     { 0xf82f69fe, "str x30, [x15, x15, lsl #0]"       },
    228     { 0xf820fbdf, "str xzr, [x30, x0, sxtx #3]"       },
    229 
    230     { 0xb85007e0, "ldr w0, [sp], #-256"               },
    231     { 0xb840040f, "ldr w15, [x0], #0"                 },
    232     { 0xb84015fe, "ldr w30, [x15], #1"                },
    233     { 0xb84ff7df, "ldr wzr, [x30], #255"              },
    234     { 0xb8100fe0, "str w0, [sp, #-256]!"              },
    235     { 0xb8000c0f, "str w15, [x0, #0]!"                },
    236     { 0xb8001dfe, "str w30, [x15, #1]!"               },
    237     { 0xb80fffdf, "str wzr, [x30, #255]!"             },
    238 
    239     { 0x13017be0, "sbfm w0, wzr, #1, #30"             },
    240     { 0x131e7fcf, "sbfm w15, w30, #30, #31"           },
    241     { 0x131f01fe, "sbfm w30, w15, #31, #0"            },
    242     { 0x1300041f, "sbfm wzr, w0, #0, #1"              },
    243 
    244     { 0x53017be0, "ubfm w0, wzr, #1, #30"             },
    245     { 0x531e7fcf, "ubfm w15, w30, #30, #31"           },
    246     { 0x531f01fe, "ubfm w30, w15, #31, #0"            },
    247     { 0x5300041f, "ubfm wzr, w0, #0, #1"              },
    248     { 0xd3417fe0, "ubfm x0, xzr, #1, #31"             },
    249     { 0xd35fffcf, "ubfm x15, x30, #31, #63"           },
    250     { 0xd35f01fe, "ubfm x30, x15, #31, #0"            },
    251     { 0xd340041f, "ubfm xzr, x0, #0, #1"              },
    252 
    253     { 0x139e7be0, "extr w0, wzr, w30, #30"            },
    254     { 0x138f7fcf, "extr w15, w30, w15, #31"           },
    255     { 0x138001fe, "extr w30, w15, w0, #0"             },
    256     { 0x139f041f, "extr wzr, w0, wzr, #1"             },
    257 
    258     { 0x54000020, "b.eq #.+4"                         },
    259     { 0x54000201, "b.ne #.+64"                        },
    260     { 0x54000802, "b.cs #.+256"                       },
    261     { 0x54002003, "b.cc #.+1024"                      },
    262     { 0x54008004, "b.mi #.+4096"                      },
    263     { 0x54ffffe5, "b.pl #.-4"                         },
    264     { 0x54ffff06, "b.vs #.-32"                        },
    265     { 0x54fffc07, "b.vc #.-128"                       },
    266     { 0x54fff008, "b.hi #.-512"                       },
    267     { 0x54000049, "b.ls #.+8"                         },
    268     { 0x5400006a, "b.ge #.+12"                        },
    269     { 0x5400008b, "b.lt #.+16"                        },
    270     { 0x54ffffcc, "b.gt #.-8"                         },
    271     { 0x54ffffad, "b.le #.-12"                        },
    272     { 0x54ffff8e, "b.al #.-16"                        },
    273 
    274     { 0x8b2001e0, "add x0, x15, w0, uxtb #0"          },
    275     { 0x8b2f27cf, "add x15, x30, w15, uxth #1"        },
    276     { 0x8b3e4bfe, "add x30, sp, w30, uxtw #2"         },
    277     { 0x8b3f6c1f, "add sp, x0, xzr, uxtx #3"          },
    278     { 0x8b2091e0, "add x0, x15, w0, sxtb #4"          },
    279     { 0x8b2fa3cf, "add x15, x30, w15, sxth #0"        },
    280     { 0x8b3ec7fe, "add x30, sp, w30, sxtw #1"         },
    281     { 0x8b3fe81f, "add sp, x0, xzr, sxtx #2"          },
    282 
    283     { 0xcb2001e0, "sub x0, x15, w0, uxtb #0"          },
    284     { 0xcb2f27cf, "sub x15, x30, w15, uxth #1"        },
    285     { 0xcb3e4bfe, "sub x30, sp, w30, uxtw #2"         },
    286     { 0xcb3f6c1f, "sub sp, x0, xzr, uxtx #3"          },
    287     { 0xcb2091e0, "sub x0, x15, w0, sxtb #4"          },
    288     { 0xcb2fa3cf, "sub x15, x30, w15, sxth #0"        },
    289     { 0xcb3ec7fe, "sub x30, sp, w30, sxtw #1"         },
    290     { 0xcb3fe81f, "sub sp, x0, xzr, sxtx #2"          }
    291 };
    292 
    293 int main()
    294 {
    295     char instr[256];
    296     uint32_t failed = 0;
    297     for(uint32_t i = 0; i < sizeof(test_table)/sizeof(test_table_entry_t); ++i)
    298     {
    299         test_table_entry_t *test;
    300         test = &test_table[i];
    301         arm64_disassemble(test->code, instr);
    302         if(strcmp(instr, test->instr) != 0)
    303         {
    304             printf("Test Failed \n"
    305                    "Code     : 0x%0x\n"
    306                    "Expected : %s\n"
    307                    "Actual   : %s\n", test->code, test->instr, instr);
    308             failed++;
    309         }
    310     }
    311     if(failed == 0)
    312     {
    313         printf("All tests PASSED\n");
    314         return 0;
    315     }
    316     else
    317     {
    318         printf("%d tests FAILED\n", failed);
    319         return -1;
    320     }
    321 }
    322