17ec681f3Smrg/*
27ec681f3Smrg * Copyright (C) 2021 Collabora, Ltd.
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
217ec681f3Smrg * SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include <stdio.h>
257ec681f3Smrg#include <inttypes.h>
267ec681f3Smrg#include "disassemble.h"
277ec681f3Smrg
287ec681f3Smrgstatic inline uint8_t
297ec681f3Smrgparse_nibble(const char c)
307ec681f3Smrg{
317ec681f3Smrg   return (c >= 'a') ? 10 + (c - 'a') : (c - '0');
327ec681f3Smrg}
337ec681f3Smrg
347ec681f3Smrg/* Given a little endian 8 byte hexdump, parse out the 64-bit value */
357ec681f3Smrgstatic uint64_t
367ec681f3Smrgparse_hex(const char *in)
377ec681f3Smrg{
387ec681f3Smrg   uint64_t v = 0;
397ec681f3Smrg
407ec681f3Smrg   for (unsigned i = 0; i < 8; ++i) {
417ec681f3Smrg      uint8_t byte = (parse_nibble(in[0]) << 4) | parse_nibble(in[1]);
427ec681f3Smrg      v |= ((uint64_t) byte) << (8 * i);
437ec681f3Smrg
447ec681f3Smrg      /* Skip the space after the byte */
457ec681f3Smrg      in += 3;
467ec681f3Smrg   }
477ec681f3Smrg
487ec681f3Smrg   return v;
497ec681f3Smrg}
507ec681f3Smrg
517ec681f3Smrgint
527ec681f3Smrgmain(int argc, const char **argv)
537ec681f3Smrg{
547ec681f3Smrg   if (argc < 2) {
557ec681f3Smrg      fprintf(stderr, "Expected case list\n");
567ec681f3Smrg      return 1;
577ec681f3Smrg   }
587ec681f3Smrg
597ec681f3Smrg   FILE *fp = fopen(argv[1], "r");
607ec681f3Smrg
617ec681f3Smrg   if (fp == NULL) {
627ec681f3Smrg      fprintf(stderr, "Could not open the case list");
637ec681f3Smrg      return 1;
647ec681f3Smrg   }
657ec681f3Smrg
667ec681f3Smrg   char line[128];
677ec681f3Smrg   unsigned nr_fail = 0, nr_pass = 0;
687ec681f3Smrg
697ec681f3Smrg   while (fgets(line, sizeof(line), fp) != NULL) {
707ec681f3Smrg      char *output = NULL;
717ec681f3Smrg      size_t sz = 0;
727ec681f3Smrg      size_t len = strlen(line);
737ec681f3Smrg
747ec681f3Smrg      /* Skip empty lines */
757ec681f3Smrg      if (len <= 1)
767ec681f3Smrg         continue;
777ec681f3Smrg
787ec681f3Smrg      /* Check for buffer overflow */
797ec681f3Smrg      if (len < 28) {
807ec681f3Smrg         fprintf(stderr, "Invalid reference %s\n", line);
817ec681f3Smrg         nr_fail++;
827ec681f3Smrg      }
837ec681f3Smrg
847ec681f3Smrg      uint64_t bin = parse_hex(line);
857ec681f3Smrg      FILE *outputp = open_memstream(&output, &sz);
867ec681f3Smrg      va_disasm_instr(outputp, bin);
877ec681f3Smrg      fprintf(outputp, "\n");
887ec681f3Smrg      fclose(outputp);
897ec681f3Smrg
907ec681f3Smrg      /* Skip hexdump: 8 bytes * (2 nibbles + 1 space) + 3 spaces */
917ec681f3Smrg      const char *reference = line + 27;
927ec681f3Smrg      bool fail = strcmp(reference, output);
937ec681f3Smrg
947ec681f3Smrg      if (fail) {
957ec681f3Smrg         printf("Got %sExpected %s\n", output, reference);
967ec681f3Smrg         nr_fail++;
977ec681f3Smrg      } else {
987ec681f3Smrg         nr_pass++;
997ec681f3Smrg      }
1007ec681f3Smrg
1017ec681f3Smrg      free(output);
1027ec681f3Smrg   }
1037ec681f3Smrg
1047ec681f3Smrg   printf("Passed %u/%u tests.\n", nr_pass, nr_pass + nr_fail);
1057ec681f3Smrg   fclose(fp);
1067ec681f3Smrg
1077ec681f3Smrg   return nr_fail ? 1 : 0;
1087ec681f3Smrg}
109