Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016, The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Elliott Hughes | 888b723 | 2024-10-28 14:31:20 +0000 | [diff] [blame] | 17 | #include <stdbool.h> |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 18 | #include <stdint.h> |
| 19 | #include <stdio.h> |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 20 | #include <stdarg.h> |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 21 | |
Maciej Żenczykowski | 63da3b2 | 2025-02-17 13:56:05 -0800 | [diff] [blame] | 22 | #include "next/apf_defs.h" |
| 23 | #include "next/apf.h" |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 24 | #include "disassembler.h" |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 25 | |
| 26 | // If "c" is of a signed type, generate a compile warning that gets promoted to an error. |
| 27 | // This makes bounds checking simpler because ">= 0" can be avoided. Otherwise adding |
| 28 | // superfluous ">= 0" with unsigned expressions generates compile warnings. |
| 29 | #define ENFORCE_UNSIGNED(c) ((c)==(uint32_t)(c)) |
| 30 | |
Yuyang Huang | 16a9e42 | 2024-01-29 09:35:06 +0900 | [diff] [blame] | 31 | char print_buf[1024]; |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 32 | char* buf_ptr; |
| 33 | int buf_remain; |
Yuyang Huang | e7956d4 | 2024-04-08 21:06:55 +0900 | [diff] [blame] | 34 | bool v6_mode = false; |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 35 | |
| 36 | __attribute__ ((format (printf, 1, 2) )) |
| 37 | static void bprintf(const char* format, ...) { |
| 38 | va_list args; |
| 39 | va_start(args, format); |
| 40 | int ret = vsnprintf(buf_ptr, buf_remain, format, args); |
| 41 | va_end(args); |
| 42 | if (ret < 0) return; |
| 43 | if (ret >= buf_remain) ret = buf_remain; |
| 44 | buf_ptr += ret; |
| 45 | buf_remain -= ret; |
| 46 | } |
| 47 | |
| 48 | static void print_opcode(const char* opcode) { |
| 49 | bprintf("%-12s", opcode); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | // Mapping from opcode number to opcode name. |
| 53 | static const char* opcode_names [] = { |
| 54 | [LDB_OPCODE] = "ldb", |
| 55 | [LDH_OPCODE] = "ldh", |
| 56 | [LDW_OPCODE] = "ldw", |
| 57 | [LDBX_OPCODE] = "ldbx", |
| 58 | [LDHX_OPCODE] = "ldhx", |
| 59 | [LDWX_OPCODE] = "ldwx", |
| 60 | [ADD_OPCODE] = "add", |
| 61 | [MUL_OPCODE] = "mul", |
| 62 | [DIV_OPCODE] = "div", |
| 63 | [AND_OPCODE] = "and", |
| 64 | [OR_OPCODE] = "or", |
| 65 | [SH_OPCODE] = "sh", |
| 66 | [LI_OPCODE] = "li", |
| 67 | [JMP_OPCODE] = "jmp", |
| 68 | [JEQ_OPCODE] = "jeq", |
| 69 | [JNE_OPCODE] = "jne", |
| 70 | [JGT_OPCODE] = "jgt", |
| 71 | [JLT_OPCODE] = "jlt", |
| 72 | [JSET_OPCODE] = "jset", |
Yuyang Huang | 0685737 | 2024-02-06 05:19:07 +0900 | [diff] [blame] | 73 | [JBSMATCH_OPCODE] = NULL, |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 74 | [LDDW_OPCODE] = "lddw", |
| 75 | [STDW_OPCODE] = "stdw", |
Yuyang Huang | 5c6ce18 | 2023-10-24 18:49:57 +0900 | [diff] [blame] | 76 | [WRITE_OPCODE] = "write", |
Maciej Żenczykowski | e0ffcb9 | 2024-05-11 08:34:27 -0700 | [diff] [blame] | 77 | [JNSET_OPCODE] = "jnset", |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 78 | }; |
| 79 | |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 80 | static void print_jump_target(uint32_t target, uint32_t program_len) { |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 81 | if (target == program_len) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 82 | bprintf("PASS"); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 83 | } else if (target == program_len + 1) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 84 | bprintf("DROP"); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 85 | } else { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 86 | bprintf("%u", target); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 87 | } |
| 88 | } |
| 89 | |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 90 | const char* apf_disassemble(const uint8_t* program, uint32_t program_len, uint32_t* const ptr2pc) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 91 | buf_ptr = print_buf; |
| 92 | buf_remain = sizeof(print_buf); |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 93 | if (*ptr2pc > program_len + 1) { |
| 94 | bprintf("pc is overflow: pc %d, program_len: %d", *ptr2pc, program_len); |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 95 | return print_buf; |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 96 | } |
| 97 | |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 98 | bprintf("%8u: ", *ptr2pc); |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 99 | |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 100 | if (*ptr2pc == program_len) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 101 | bprintf("PASS"); |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 102 | ++(*ptr2pc); |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 103 | return print_buf; |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 104 | } |
| 105 | |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 106 | if (*ptr2pc == program_len + 1) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 107 | bprintf("DROP"); |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 108 | ++(*ptr2pc); |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 109 | return print_buf; |
| 110 | } |
| 111 | |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 112 | const uint8_t bytecode = program[(*ptr2pc)++]; |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 113 | const uint32_t opcode = EXTRACT_OPCODE(bytecode); |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 114 | |
| 115 | #define PRINT_OPCODE() print_opcode(opcode_names[opcode]) |
Yuyang Huang | 186a80f | 2024-02-06 10:24:08 +0900 | [diff] [blame] | 116 | #define DECODE_IMM(length) ({ \ |
| 117 | uint32_t value = 0; \ |
| 118 | for (uint32_t i = 0; i < (length) && *ptr2pc < program_len; i++) \ |
| 119 | value = (value << 8) | program[(*ptr2pc)++]; \ |
| 120 | value;}) |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 121 | |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 122 | const uint32_t reg_num = EXTRACT_REGISTER(bytecode); |
| 123 | // All instructions have immediate fields, so load them now. |
| 124 | const uint32_t len_field = EXTRACT_IMM_LENGTH(bytecode); |
| 125 | uint32_t imm = 0; |
| 126 | int32_t signed_imm = 0; |
| 127 | if (len_field != 0) { |
| 128 | const uint32_t imm_len = 1 << (len_field - 1); |
Yuyang Huang | 186a80f | 2024-02-06 10:24:08 +0900 | [diff] [blame] | 129 | imm = DECODE_IMM(imm_len); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 130 | // Sign extend imm into signed_imm. |
| 131 | signed_imm = imm << ((4 - imm_len) * 8); |
| 132 | signed_imm >>= (4 - imm_len) * 8; |
| 133 | } |
| 134 | switch (opcode) { |
Yuyang Huang | 2b7763f | 2024-01-29 06:34:01 +0900 | [diff] [blame] | 135 | case PASSDROP_OPCODE: |
| 136 | if (reg_num == 0) { |
| 137 | print_opcode("pass"); |
| 138 | } else { |
| 139 | print_opcode("drop"); |
| 140 | } |
Yuyang Huang | ddd3b86 | 2024-01-29 11:46:16 +0900 | [diff] [blame] | 141 | if (imm > 0) { |
Yuyang Huang | 19e74c3 | 2024-04-09 01:22:06 +0900 | [diff] [blame] | 142 | bprintf("counter=%d", imm); |
Yuyang Huang | 2b7763f | 2024-01-29 06:34:01 +0900 | [diff] [blame] | 143 | } |
| 144 | break; |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 145 | case LDB_OPCODE: |
| 146 | case LDH_OPCODE: |
| 147 | case LDW_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 148 | PRINT_OPCODE(); |
| 149 | bprintf("r%d, [%u]", reg_num, imm); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 150 | break; |
| 151 | case LDBX_OPCODE: |
| 152 | case LDHX_OPCODE: |
| 153 | case LDWX_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 154 | PRINT_OPCODE(); |
Maciej Żenczykowski | 8dee633 | 2023-09-05 02:28:26 +0000 | [diff] [blame] | 155 | if (imm) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 156 | bprintf("r%d, [r1+%u]", reg_num, imm); |
Maciej Żenczykowski | 8dee633 | 2023-09-05 02:28:26 +0000 | [diff] [blame] | 157 | } else { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 158 | bprintf("r%d, [r1]", reg_num); |
Maciej Żenczykowski | 8dee633 | 2023-09-05 02:28:26 +0000 | [diff] [blame] | 159 | } |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 160 | break; |
| 161 | case JMP_OPCODE: |
Yuyang Huang | 16a9e42 | 2024-01-29 09:35:06 +0900 | [diff] [blame] | 162 | if (reg_num == 0) { |
| 163 | PRINT_OPCODE(); |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 164 | print_jump_target(*ptr2pc + imm, program_len); |
Yuyang Huang | 16a9e42 | 2024-01-29 09:35:06 +0900 | [diff] [blame] | 165 | } else { |
Yuyang Huang | e7956d4 | 2024-04-08 21:06:55 +0900 | [diff] [blame] | 166 | v6_mode = true; |
Yuyang Huang | 16a9e42 | 2024-01-29 09:35:06 +0900 | [diff] [blame] | 167 | print_opcode("data"); |
Yuyang Huang | 61e63d2 | 2024-02-04 07:19:33 +0900 | [diff] [blame] | 168 | bprintf("%d, ", imm); |
Yuyang Huang | 16a9e42 | 2024-01-29 09:35:06 +0900 | [diff] [blame] | 169 | uint32_t len = imm; |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 170 | while (len--) bprintf("%02x", program[(*ptr2pc)++]); |
Yuyang Huang | 16a9e42 | 2024-01-29 09:35:06 +0900 | [diff] [blame] | 171 | } |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 172 | break; |
| 173 | case JEQ_OPCODE: |
| 174 | case JNE_OPCODE: |
| 175 | case JGT_OPCODE: |
| 176 | case JLT_OPCODE: |
Maciej Żenczykowski | e0ffcb9 | 2024-05-11 08:34:27 -0700 | [diff] [blame] | 177 | case JSET_OPCODE: |
| 178 | case JNSET_OPCODE: { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 179 | PRINT_OPCODE(); |
| 180 | bprintf("r0, "); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 181 | // Load second immediate field. |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 182 | if (reg_num == 1) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 183 | bprintf("r1, "); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 184 | } else if (len_field == 0) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 185 | bprintf("0, "); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 186 | } else { |
Yuyang Huang | 186a80f | 2024-02-06 10:24:08 +0900 | [diff] [blame] | 187 | uint32_t cmp_imm = DECODE_IMM(1 << (len_field - 1)); |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 188 | bprintf("0x%x, ", cmp_imm); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 189 | } |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 190 | print_jump_target(*ptr2pc + imm, program_len); |
Yuyang Huang | 79fa121 | 2024-02-04 07:42:51 +0900 | [diff] [blame] | 191 | break; |
| 192 | } |
Yuyang Huang | 0685737 | 2024-02-06 05:19:07 +0900 | [diff] [blame] | 193 | case JBSMATCH_OPCODE: { |
Yuyang Huang | 79fa121 | 2024-02-04 07:42:51 +0900 | [diff] [blame] | 194 | if (reg_num == 0) { |
Yuyang Huang | 0685737 | 2024-02-06 05:19:07 +0900 | [diff] [blame] | 195 | print_opcode("jbsne"); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 196 | } else { |
Yuyang Huang | 0685737 | 2024-02-06 05:19:07 +0900 | [diff] [blame] | 197 | print_opcode("jbseq"); |
Yuyang Huang | 79fa121 | 2024-02-04 07:42:51 +0900 | [diff] [blame] | 198 | } |
| 199 | bprintf("r0, "); |
Yuyang Huang | 6df7e7b | 2024-04-26 17:58:20 +0900 | [diff] [blame] | 200 | const uint32_t cmp_imm = DECODE_IMM(1 << (len_field - 1)); |
| 201 | const uint32_t cnt = (cmp_imm >> 11) + 1; // 1+, up to 32 fits in u16 |
| 202 | const uint32_t len = cmp_imm & 2047; // 0..2047 |
| 203 | bprintf("0x%x, ", len); |
| 204 | print_jump_target(*ptr2pc + imm + cnt * len, program_len); |
Yuyang Huang | 79fa121 | 2024-02-04 07:42:51 +0900 | [diff] [blame] | 205 | bprintf(", "); |
Yuyang Huang | 6df7e7b | 2024-04-26 17:58:20 +0900 | [diff] [blame] | 206 | if (cnt > 1) { |
| 207 | bprintf("{ "); |
| 208 | } |
| 209 | for (uint32_t i = 0; i < cnt; ++i) { |
| 210 | for (uint32_t j = 0; j < len; ++j) { |
| 211 | uint8_t byte = program[(*ptr2pc)++]; |
| 212 | bprintf("%02x", byte); |
| 213 | } |
| 214 | if (i != cnt - 1) { |
| 215 | bprintf(", "); |
| 216 | } |
| 217 | } |
| 218 | if (cnt > 1) { |
| 219 | bprintf(" }"); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 220 | } |
| 221 | break; |
| 222 | } |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 223 | case SH_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 224 | PRINT_OPCODE(); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 225 | if (reg_num) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 226 | bprintf("r0, r1"); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 227 | } else { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 228 | bprintf("r0, %d", signed_imm); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 229 | } |
| 230 | break; |
Maciej Żenczykowski | bea1b99 | 2023-09-03 16:09:04 +0000 | [diff] [blame] | 231 | case ADD_OPCODE: |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 232 | case MUL_OPCODE: |
| 233 | case DIV_OPCODE: |
| 234 | case AND_OPCODE: |
| 235 | case OR_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 236 | PRINT_OPCODE(); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 237 | if (reg_num) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 238 | bprintf("r0, r1"); |
Maciej Żenczykowski | b64968d | 2023-09-05 23:08:11 +0000 | [diff] [blame] | 239 | } else if (!imm && opcode == DIV_OPCODE) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 240 | bprintf("pass (div 0)"); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 241 | } else { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 242 | bprintf("r0, %u", imm); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 243 | } |
| 244 | break; |
| 245 | case LI_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 246 | PRINT_OPCODE(); |
| 247 | bprintf("r%d, %d", reg_num, signed_imm); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 248 | break; |
| 249 | case EXT_OPCODE: |
| 250 | if ( |
| 251 | // If LDM_EXT_OPCODE is 0 and imm is compared with it, a compiler error will result, |
| 252 | // instead just enforce that imm is unsigned (so it's always greater or equal to 0). |
| 253 | #if LDM_EXT_OPCODE == 0 |
| 254 | ENFORCE_UNSIGNED(imm) && |
| 255 | #else |
| 256 | imm >= LDM_EXT_OPCODE && |
| 257 | #endif |
| 258 | imm < (LDM_EXT_OPCODE + MEMORY_ITEMS)) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 259 | print_opcode("ldm"); |
| 260 | bprintf("r%d, m[%u]", reg_num, imm - LDM_EXT_OPCODE); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 261 | } else if (imm >= STM_EXT_OPCODE && imm < (STM_EXT_OPCODE + MEMORY_ITEMS)) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 262 | print_opcode("stm"); |
| 263 | bprintf("r%d, m[%u]", reg_num, imm - STM_EXT_OPCODE); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 264 | } else switch (imm) { |
| 265 | case NOT_EXT_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 266 | print_opcode("not"); |
| 267 | bprintf("r%d", reg_num); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 268 | break; |
| 269 | case NEG_EXT_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 270 | print_opcode("neg"); |
| 271 | bprintf("r%d", reg_num); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 272 | break; |
| 273 | case SWAP_EXT_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 274 | print_opcode("swap"); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 275 | break; |
| 276 | case MOV_EXT_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 277 | print_opcode("mov"); |
| 278 | bprintf("r%d, r%d", reg_num, reg_num ^ 1); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 279 | break; |
Yuyang Huang | a341661 | 2024-01-26 08:18:30 +0900 | [diff] [blame] | 280 | case ALLOCATE_EXT_OPCODE: |
Yuyang Huang | 037d3df | 2024-01-29 06:52:24 +0900 | [diff] [blame] | 281 | print_opcode("allocate"); |
| 282 | if (reg_num == 0) { |
| 283 | bprintf("r%d", reg_num); |
| 284 | } else { |
Yuyang Huang | 186a80f | 2024-02-06 10:24:08 +0900 | [diff] [blame] | 285 | uint32_t alloc_len = DECODE_IMM(2); |
Yuyang Huang | 037d3df | 2024-01-29 06:52:24 +0900 | [diff] [blame] | 286 | bprintf("%d", alloc_len); |
| 287 | } |
Yuyang Huang | 9aece5c | 2023-10-16 17:45:35 +0900 | [diff] [blame] | 288 | break; |
Maciej Żenczykowski | d02a691 | 2024-02-09 22:37:40 -0800 | [diff] [blame] | 289 | case TRANSMIT_EXT_OPCODE: |
| 290 | print_opcode(reg_num ? "transmitudp" : "transmit"); |
| 291 | u8 ip_ofs = DECODE_IMM(1); |
| 292 | u8 csum_ofs = DECODE_IMM(1); |
| 293 | if (csum_ofs < 255) { |
| 294 | u8 csum_start = DECODE_IMM(1); |
| 295 | u16 partial_csum = DECODE_IMM(2); |
| 296 | bprintf("ip_ofs=%d, csum_ofs=%d, csum_start=%d, partial_csum=0x%04x", |
| 297 | ip_ofs, csum_ofs, csum_start, partial_csum); |
| 298 | } else { |
| 299 | bprintf("ip_ofs=%d", ip_ofs); |
Yuyang Huang | a96ba55 | 2024-01-29 07:15:08 +0900 | [diff] [blame] | 300 | } |
Yuyang Huang | 9aece5c | 2023-10-16 17:45:35 +0900 | [diff] [blame] | 301 | break; |
Yuyang Huang | e2507e3 | 2024-01-30 03:36:31 +0900 | [diff] [blame] | 302 | case EWRITE1_EXT_OPCODE: print_opcode("ewrite1"); bprintf("r%d", reg_num); break; |
| 303 | case EWRITE2_EXT_OPCODE: print_opcode("ewrite2"); bprintf("r%d", reg_num); break; |
| 304 | case EWRITE4_EXT_OPCODE: print_opcode("ewrite4"); bprintf("r%d", reg_num); break; |
Yuyang Huang | f6ed43c | 2024-02-03 15:34:20 +0900 | [diff] [blame] | 305 | case EPKTDATACOPYIMM_EXT_OPCODE: |
| 306 | case EPKTDATACOPYR1_EXT_OPCODE: { |
| 307 | if (reg_num == 0) { |
| 308 | print_opcode("epktcopy"); |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 309 | } else { |
Yuyang Huang | f6ed43c | 2024-02-03 15:34:20 +0900 | [diff] [blame] | 310 | print_opcode("edatacopy"); |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 311 | } |
Yuyang Huang | f6ed43c | 2024-02-03 15:34:20 +0900 | [diff] [blame] | 312 | if (imm == EPKTDATACOPYIMM_EXT_OPCODE) { |
Yuyang Huang | 186a80f | 2024-02-06 10:24:08 +0900 | [diff] [blame] | 313 | uint32_t len = DECODE_IMM(1); |
Yuyang Huang | 1a14958 | 2024-02-06 12:40:53 +0900 | [diff] [blame] | 314 | bprintf(" src=r0, len=%d", len); |
Yuyang Huang | f6ed43c | 2024-02-03 15:34:20 +0900 | [diff] [blame] | 315 | } else { |
Yuyang Huang | 1a14958 | 2024-02-06 12:40:53 +0900 | [diff] [blame] | 316 | bprintf(" src=r0, len=r1"); |
Yuyang Huang | f6ed43c | 2024-02-03 15:34:20 +0900 | [diff] [blame] | 317 | } |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 318 | |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 319 | break; |
| 320 | } |
Yuyang Huang | 8098da1 | 2024-02-14 22:00:51 +0900 | [diff] [blame] | 321 | case JDNSQMATCH_EXT_OPCODE: // 43 |
| 322 | case JDNSAMATCH_EXT_OPCODE: // 44 |
| 323 | case JDNSQMATCHSAFE_EXT_OPCODE: // 45 |
| 324 | case JDNSAMATCHSAFE_EXT_OPCODE: { // 46 |
Yuyang Huang | 869a374 | 2024-02-07 04:01:29 +0900 | [diff] [blame] | 325 | uint32_t offs = DECODE_IMM(1 << (len_field - 1)); |
Yuyang Huang | 8098da1 | 2024-02-14 22:00:51 +0900 | [diff] [blame] | 326 | int qtype = -1; |
| 327 | switch(imm) { |
| 328 | case JDNSQMATCH_EXT_OPCODE: |
| 329 | print_opcode(reg_num ? "jdnsqeq" : "jdnsqne"); |
| 330 | qtype = DECODE_IMM(1); |
| 331 | break; |
| 332 | case JDNSQMATCHSAFE_EXT_OPCODE: |
| 333 | print_opcode(reg_num ? "jdnsqeqsafe" : "jdnsqnesafe"); |
| 334 | qtype = DECODE_IMM(1); |
| 335 | break; |
| 336 | case JDNSAMATCH_EXT_OPCODE: |
| 337 | print_opcode(reg_num ? "jdnsaeq" : "jdnsane"); break; |
| 338 | case JDNSAMATCHSAFE_EXT_OPCODE: |
| 339 | print_opcode(reg_num ? "jdnsaeqsafe" : "jdnsanesafe"); break; |
| 340 | default: |
| 341 | bprintf("unknown_ext %u", imm); break; |
Yuyang Huang | 7c7d8fe | 2024-02-04 09:38:32 +0900 | [diff] [blame] | 342 | } |
| 343 | bprintf("r0, "); |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 344 | uint32_t end = *ptr2pc; |
Yuyang Huang | 7c7d8fe | 2024-02-04 09:38:32 +0900 | [diff] [blame] | 345 | while (end + 1 < program_len && !(program[end] == 0 && program[end + 1] == 0)) { |
| 346 | end++; |
| 347 | } |
| 348 | end += 2; |
| 349 | print_jump_target(end + offs, program_len); |
Yuyang Huang | 869a374 | 2024-02-07 04:01:29 +0900 | [diff] [blame] | 350 | bprintf(", "); |
Yuyang Huang | 8098da1 | 2024-02-14 22:00:51 +0900 | [diff] [blame] | 351 | if (imm == JDNSQMATCH_EXT_OPCODE || imm == JDNSQMATCHSAFE_EXT_OPCODE) { |
Yuyang Huang | 869a374 | 2024-02-07 04:01:29 +0900 | [diff] [blame] | 352 | bprintf("%d, ", qtype); |
| 353 | } |
Yuyang Huang | 591860d | 2024-02-06 06:58:30 +0900 | [diff] [blame] | 354 | while (*ptr2pc < end) { |
| 355 | uint8_t byte = program[(*ptr2pc)++]; |
Yuyang Huang | d486dd0 | 2025-02-18 15:38:14 +0900 | [diff] [blame] | 356 | // value == 0xff is a wildcard that consumes the whole label. |
Yuyang Huang | 869a374 | 2024-02-07 04:01:29 +0900 | [diff] [blame] | 357 | // values < 0x40 could be lengths, but - and 0..9 are in practice usually |
| 358 | // too long to be lengths so print them as characters. All other chars < 0x40 |
| 359 | // are not valid in dns character. |
Yuyang Huang | d486dd0 | 2025-02-18 15:38:14 +0900 | [diff] [blame] | 360 | if (byte == 0xff) { |
| 361 | bprintf("(*)"); |
| 362 | } else if (byte == '-' || (byte >= '0' && byte <= '9') || byte >= 0x40) { |
Yuyang Huang | 869a374 | 2024-02-07 04:01:29 +0900 | [diff] [blame] | 363 | bprintf("%c", byte); |
| 364 | } else { |
| 365 | bprintf("(%d)", byte); |
| 366 | } |
Yuyang Huang | 7c7d8fe | 2024-02-04 09:38:32 +0900 | [diff] [blame] | 367 | } |
| 368 | break; |
| 369 | } |
Yuyang Huang | eda4335 | 2024-04-21 19:38:56 +0900 | [diff] [blame] | 370 | case JONEOF_EXT_OPCODE: { |
| 371 | const uint32_t imm_len = 1 << (len_field - 1); |
| 372 | uint32_t jump_offs = DECODE_IMM(imm_len); |
| 373 | uint8_t imm3 = DECODE_IMM(1); |
| 374 | bool jmp = imm3 & 1; |
| 375 | uint8_t len = ((imm3 >> 1) & 3) + 1; |
| 376 | uint8_t cnt = (imm3 >> 3) + 2; |
| 377 | if (jmp) { |
| 378 | print_opcode("jnoneof"); |
| 379 | } else { |
| 380 | print_opcode("joneof"); |
| 381 | } |
| 382 | bprintf("r%d, ", reg_num); |
| 383 | print_jump_target(*ptr2pc + jump_offs + cnt * len, program_len); |
| 384 | bprintf(", { "); |
| 385 | while (cnt--) { |
| 386 | uint32_t v = DECODE_IMM(len); |
| 387 | if (cnt) { |
| 388 | bprintf("%d, ", v); |
| 389 | } else { |
| 390 | bprintf("%d ", v); |
| 391 | } |
| 392 | } |
| 393 | bprintf("}"); |
| 394 | break; |
| 395 | } |
Yuyang Huang | e8da73e | 2024-04-30 18:02:01 +0900 | [diff] [blame] | 396 | case EXCEPTIONBUFFER_EXT_OPCODE: { |
| 397 | uint32_t buf_size = DECODE_IMM(2); |
| 398 | print_opcode("debugbuf"); |
| 399 | bprintf("size=%d", buf_size); |
| 400 | break; |
| 401 | } |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 402 | default: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 403 | bprintf("unknown_ext %u", imm); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 404 | break; |
| 405 | } |
| 406 | break; |
| 407 | case LDDW_OPCODE: |
| 408 | case STDW_OPCODE: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 409 | PRINT_OPCODE(); |
Yuyang Huang | e7956d4 | 2024-04-08 21:06:55 +0900 | [diff] [blame] | 410 | if (v6_mode) { |
| 411 | if (opcode == LDDW_OPCODE) { |
Maciej Żenczykowski | a7ad6eb | 2024-04-08 22:44:24 -0700 | [diff] [blame] | 412 | bprintf("r%u, counter=%d", reg_num, imm); |
Yuyang Huang | e7956d4 | 2024-04-08 21:06:55 +0900 | [diff] [blame] | 413 | } else { |
Maciej Żenczykowski | a7ad6eb | 2024-04-08 22:44:24 -0700 | [diff] [blame] | 414 | bprintf("counter=%d, r%u", imm, reg_num); |
Yuyang Huang | e7956d4 | 2024-04-08 21:06:55 +0900 | [diff] [blame] | 415 | } |
Maciej Żenczykowski | 8dee633 | 2023-09-05 02:28:26 +0000 | [diff] [blame] | 416 | } else { |
Yuyang Huang | e7956d4 | 2024-04-08 21:06:55 +0900 | [diff] [blame] | 417 | if (signed_imm > 0) { |
| 418 | bprintf("r%u, [r%u+%d]", reg_num, reg_num ^ 1, signed_imm); |
| 419 | } else if (signed_imm < 0) { |
| 420 | bprintf("r%u, [r%u-%d]", reg_num, reg_num ^ 1, -signed_imm); |
| 421 | } else { |
| 422 | bprintf("r%u, [r%u]", reg_num, reg_num ^ 1); |
| 423 | } |
Maciej Żenczykowski | 8dee633 | 2023-09-05 02:28:26 +0000 | [diff] [blame] | 424 | } |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 425 | break; |
Yuyang Huang | 5c6ce18 | 2023-10-24 18:49:57 +0900 | [diff] [blame] | 426 | case WRITE_OPCODE: { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 427 | PRINT_OPCODE(); |
Yuyang Huang | 5c6ce18 | 2023-10-24 18:49:57 +0900 | [diff] [blame] | 428 | uint32_t write_len = 1 << (len_field - 1); |
| 429 | if (write_len > 0) { |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 430 | bprintf("0x"); |
Yuyang Huang | 5c6ce18 | 2023-10-24 18:49:57 +0900 | [diff] [blame] | 431 | } |
| 432 | for (uint32_t i = 0; i < write_len; ++i) { |
| 433 | uint8_t byte = |
| 434 | (uint8_t) ((imm >> (write_len - 1 - i) * 8) & 0xff); |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 435 | bprintf("%02x", byte); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 436 | |
Yuyang Huang | 5c6ce18 | 2023-10-24 18:49:57 +0900 | [diff] [blame] | 437 | } |
| 438 | break; |
| 439 | } |
Yuyang Huang | a341661 | 2024-01-26 08:18:30 +0900 | [diff] [blame] | 440 | case PKTDATACOPY_OPCODE: { |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 441 | if (reg_num == 0) { |
Yuyang Huang | fb0e167 | 2024-02-07 06:28:46 +0900 | [diff] [blame] | 442 | print_opcode("pktcopy"); |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 443 | } else { |
Yuyang Huang | fb0e167 | 2024-02-07 06:28:46 +0900 | [diff] [blame] | 444 | print_opcode("datacopy"); |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 445 | } |
Yuyang Huang | 7dd27fa | 2024-01-30 04:05:18 +0900 | [diff] [blame] | 446 | uint32_t src_offs = imm; |
Yuyang Huang | 186a80f | 2024-02-06 10:24:08 +0900 | [diff] [blame] | 447 | uint32_t copy_len = DECODE_IMM(1); |
Yuyang Huang | 1a14958 | 2024-02-06 12:40:53 +0900 | [diff] [blame] | 448 | bprintf("src=%d, len=%d", src_offs, copy_len); |
Yuyang Huang | aea452e | 2023-11-01 18:14:45 +0900 | [diff] [blame] | 449 | break; |
| 450 | } |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 451 | // Unknown opcode |
| 452 | default: |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 453 | bprintf("unknown %u", opcode); |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 454 | break; |
| 455 | } |
Yuyang Huang | 3212258 | 2024-01-28 06:52:53 +0900 | [diff] [blame] | 456 | return print_buf; |
Lorenzo Colitti | 983eb51 | 2019-09-26 22:14:16 +0900 | [diff] [blame] | 457 | } |