instructions.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/compiler.h>
  3. static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
  4. struct map_symbol *ms)
  5. {
  6. char *endptr, *tok, *name;
  7. struct map *map = ms->map;
  8. struct addr_map_symbol target = {
  9. .map = map,
  10. };
  11. tok = strchr(ops->raw, ',');
  12. if (!tok)
  13. return -1;
  14. ops->target.addr = strtoull(tok + 1, &endptr, 16);
  15. name = strchr(endptr, '<');
  16. if (name == NULL)
  17. return -1;
  18. name++;
  19. if (arch->objdump.skip_functions_char &&
  20. strchr(name, arch->objdump.skip_functions_char))
  21. return -1;
  22. tok = strchr(name, '>');
  23. if (tok == NULL)
  24. return -1;
  25. *tok = '\0';
  26. ops->target.name = strdup(name);
  27. *tok = '>';
  28. if (ops->target.name == NULL)
  29. return -1;
  30. target.addr = map__objdump_2mem(map, ops->target.addr);
  31. if (map_groups__find_ams(&target) == 0 &&
  32. map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
  33. ops->target.sym = target.sym;
  34. return 0;
  35. }
  36. static int call__scnprintf(struct ins *ins, char *bf, size_t size,
  37. struct ins_operands *ops);
  38. static struct ins_ops s390_call_ops = {
  39. .parse = s390_call__parse,
  40. .scnprintf = call__scnprintf,
  41. };
  42. static int s390_mov__parse(struct arch *arch __maybe_unused,
  43. struct ins_operands *ops,
  44. struct map_symbol *ms __maybe_unused)
  45. {
  46. char *s = strchr(ops->raw, ','), *target, *endptr;
  47. if (s == NULL)
  48. return -1;
  49. *s = '\0';
  50. ops->source.raw = strdup(ops->raw);
  51. *s = ',';
  52. if (ops->source.raw == NULL)
  53. return -1;
  54. target = ++s;
  55. ops->target.raw = strdup(target);
  56. if (ops->target.raw == NULL)
  57. goto out_free_source;
  58. ops->target.addr = strtoull(target, &endptr, 16);
  59. if (endptr == target)
  60. goto out_free_target;
  61. s = strchr(endptr, '<');
  62. if (s == NULL)
  63. goto out_free_target;
  64. endptr = strchr(s + 1, '>');
  65. if (endptr == NULL)
  66. goto out_free_target;
  67. *endptr = '\0';
  68. ops->target.name = strdup(s + 1);
  69. *endptr = '>';
  70. if (ops->target.name == NULL)
  71. goto out_free_target;
  72. return 0;
  73. out_free_target:
  74. zfree(&ops->target.raw);
  75. out_free_source:
  76. zfree(&ops->source.raw);
  77. return -1;
  78. }
  79. static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
  80. struct ins_operands *ops);
  81. static struct ins_ops s390_mov_ops = {
  82. .parse = s390_mov__parse,
  83. .scnprintf = mov__scnprintf,
  84. };
  85. static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
  86. {
  87. struct ins_ops *ops = NULL;
  88. /* catch all kind of jumps */
  89. if (strchr(name, 'j') ||
  90. !strncmp(name, "bct", 3) ||
  91. !strncmp(name, "br", 2))
  92. ops = &jump_ops;
  93. /* override call/returns */
  94. if (!strcmp(name, "bras") ||
  95. !strcmp(name, "brasl") ||
  96. !strcmp(name, "basr"))
  97. ops = &s390_call_ops;
  98. if (!strcmp(name, "br"))
  99. ops = &ret_ops;
  100. /* override load/store relative to PC */
  101. if (!strcmp(name, "lrl") ||
  102. !strcmp(name, "lgrl") ||
  103. !strcmp(name, "lgfrl") ||
  104. !strcmp(name, "llgfrl") ||
  105. !strcmp(name, "strl") ||
  106. !strcmp(name, "stgrl"))
  107. ops = &s390_mov_ops;
  108. if (ops)
  109. arch__associate_ins_ops(arch, name, ops);
  110. return ops;
  111. }
  112. static int s390__cpuid_parse(struct arch *arch, char *cpuid)
  113. {
  114. unsigned int family;
  115. char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
  116. int ret;
  117. /*
  118. * cpuid string format:
  119. * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
  120. */
  121. ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
  122. model, cpumf_v, cpumf_a);
  123. if (ret >= 2) {
  124. arch->family = family;
  125. arch->model = 0;
  126. return 0;
  127. }
  128. return -1;
  129. }
  130. static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
  131. {
  132. int err = 0;
  133. if (!arch->initialized) {
  134. arch->initialized = true;
  135. arch->associate_instruction_ops = s390__associate_ins_ops;
  136. if (cpuid)
  137. err = s390__cpuid_parse(arch, cpuid);
  138. }
  139. return err;
  140. }