/*************************************************************************************** * Copyright (c) 2014-2022 Zihao Yu, Nanjing University * * NEMU is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * * See the Mulan PSL v2 for more details. ***************************************************************************************/ #ifndef __CPU_DECODE_H__ #define __CPU_DECODE_H__ #include "types.h" #include typedef enum { INST_NORMAL, INST_MEM_WRITE, INST_MEM_READ } inst_type_t; typedef union { paddr_t rmem; paddr_t wmem; } inst_type_op; typedef struct Decode { vaddr_t pc; vaddr_t snpc; // static next pc vaddr_t dnpc; // dynamic next pc inst_type_t inst_type; inst_type_op inst_value; ISADecodeInfo isa; } Decode; // --- pattern matching mechanism --- __attribute__((always_inline)) static inline void pattern_decode(const char *str, int len, uint64_t *key, uint64_t *mask, uint64_t *shift) { uint64_t __key = 0, __mask = 0, __shift = 0; #define macro(i) \ if ((i) >= len) \ goto finish; \ else { \ char c = str[i]; \ if (c != ' ') { \ Assert(c == '0' || c == '1' || c == '?', \ "invalid character '%c' in pattern string", c); \ __key = (__key << 1) | (c == '1' ? 1 : 0); \ __mask = (__mask << 1) | (c == '?' ? 0 : 1); \ __shift = (c == '?' ? __shift + 1 : 0); \ } \ } #define macro2(i) \ macro(i); \ macro((i) + 1) #define macro4(i) \ macro2(i); \ macro2((i) + 2) #define macro8(i) \ macro4(i); \ macro4((i) + 4) #define macro16(i) \ macro8(i); \ macro8((i) + 8) #define macro32(i) \ macro16(i); \ macro16((i) + 16) #define macro64(i) \ macro32(i); \ macro32((i) + 32) macro64(0); panic("pattern too long"); #undef macro finish: *key = __key >> __shift; *mask = __mask >> __shift; *shift = __shift; } __attribute__((always_inline)) static inline void pattern_decode_hex(const char *str, int len, uint64_t *key, uint64_t *mask, uint64_t *shift) { uint64_t __key = 0, __mask = 0, __shift = 0; #define macro(i) \ if ((i) >= len) \ goto finish; \ else { \ char c = str[i]; \ if (c != ' ') { \ Assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || c == '?', \ "invalid character '%c' in pattern string", c); \ __key = (__key << 4) | (c == '?' ? 0 \ : (c >= '0' && c <= '9') ? c - '0' \ : c - 'a' + 10); \ __mask = (__mask << 4) | (c == '?' ? 0 : 0xf); \ __shift = (c == '?' ? __shift + 4 : 0); \ } \ } macro16(0); panic("pattern too long"); #undef macro finish: *key = __key >> __shift; *mask = __mask >> __shift; *shift = __shift; } // --- pattern matching wrappers for decode --- #define INSTPAT(pattern, ...) \ do { \ uint64_t key, mask, shift; \ pattern_decode(pattern, STRLEN(pattern), &key, &mask, &shift); \ if ((((uint64_t)INSTPAT_INST(s) >> shift) & mask) == key) { \ INSTPAT_MATCH(s, ##__VA_ARGS__); \ goto *(__instpat_end); \ } \ } while (0) #define INSTPAT_START(name) \ { \ const void **__instpat_end = &&concat(__instpat_end_, name); #define INSTPAT_END(name) \ concat(__instpat_end_, name) :; \ } #endif