ysyx-workbench/nemu/include/cpu/decode.h

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