131 lines
6 KiB
C
131 lines
6 KiB
C
/***************************************************************************************
|
|
* 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 <isa.h>
|
|
|
|
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
|