419 lines
10 KiB
C
419 lines
10 KiB
C
/* decode.h -- Prototypes for AArch64 simulator decoder functions.
|
|
|
|
Copyright (C) 2015-2016 Free Software Foundation, Inc.
|
|
|
|
Contributed by Red Hat.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef _DECODE_H
|
|
#define _DECODE_H
|
|
|
|
#include <sys/types.h>
|
|
#include "cpustate.h"
|
|
|
|
/* Codes used in conditional instructions
|
|
|
|
These are passed to conditional operations to identify which
|
|
condition to test for. */
|
|
|
|
typedef enum CondCode
|
|
{
|
|
EQ = 0x0, /* meaning Z == 1 */
|
|
NE = 0x1, /* meaning Z == 0 */
|
|
HS = 0x2, /* meaning C == 1 */
|
|
CS = HS,
|
|
LO = 0x3, /* meaning C == 0 */
|
|
CC = LO,
|
|
MI = 0x4, /* meaning N == 1 */
|
|
PL = 0x5, /* meaning N == 0 */
|
|
VS = 0x6, /* meaning V == 1 */
|
|
VC = 0x7, /* meaning V == 0 */
|
|
HI = 0x8, /* meaning C == 1 && Z == 0 */
|
|
LS = 0x9, /* meaning !(C == 1 && Z == 0) */
|
|
GE = 0xa, /* meaning N == V */
|
|
LT = 0xb, /* meaning N != V */
|
|
GT = 0xc, /* meaning Z == 0 && N == V */
|
|
LE = 0xd, /* meaning !(Z == 0 && N == V) */
|
|
AL = 0xe, /* meaning ANY */
|
|
NV = 0xf /* ditto */
|
|
} CondCode;
|
|
|
|
/* Certain addressing modes for load require pre or post writeback of
|
|
the computed address to a base register. */
|
|
|
|
typedef enum WriteBack
|
|
{
|
|
Post = 0,
|
|
Pre = 1,
|
|
NoWriteBack = -1
|
|
} WriteBack;
|
|
|
|
/* Certain addressing modes for load require an offset to
|
|
be optionally scaled so the decode needs to pass that
|
|
through to the execute routine. */
|
|
|
|
typedef enum Scaling
|
|
{
|
|
Unscaled = 0,
|
|
Scaled = 1,
|
|
NoScaling = -1
|
|
} Scaling;
|
|
|
|
/* When we do have to scale we do so by shifting using
|
|
log(bytes in data element - 1) as the shift count.
|
|
so we don't have to scale offsets when loading
|
|
bytes. */
|
|
|
|
typedef enum ScaleShift
|
|
{
|
|
ScaleShift16 = 1,
|
|
ScaleShift32 = 2,
|
|
ScaleShift64 = 3,
|
|
ScaleShift128 = 4
|
|
} ScaleShift;
|
|
|
|
/* One of the addressing modes for load requires a 32-bit register
|
|
value to be either zero- or sign-extended for these instructions
|
|
UXTW or SXTW should be passed.
|
|
|
|
Arithmetic register data processing operations can optionally
|
|
extend a portion of the second register value for these
|
|
instructions the value supplied must identify the portion of the
|
|
register which is to be zero- or sign-exended. */
|
|
|
|
typedef enum Extension
|
|
{
|
|
UXTB = 0,
|
|
UXTH = 1,
|
|
UXTW = 2,
|
|
UXTX = 3,
|
|
SXTB = 4,
|
|
SXTH = 5,
|
|
SXTW = 6,
|
|
SXTX = 7,
|
|
NoExtension = -1
|
|
} Extension;
|
|
|
|
/* Arithmetic and logical register data processing operations
|
|
optionally perform a shift on the second register value. */
|
|
|
|
typedef enum Shift
|
|
{
|
|
LSL = 0,
|
|
LSR = 1,
|
|
ASR = 2,
|
|
ROR = 3
|
|
} Shift;
|
|
|
|
/* Bit twiddling helpers for instruction decode. */
|
|
|
|
/* 32 bit mask with bits [hi,...,lo] set. */
|
|
static inline uint32_t
|
|
mask32 (int hi, int lo)
|
|
{
|
|
int nbits = (hi + 1) - lo;
|
|
return ((1 << nbits) - 1) << lo;
|
|
}
|
|
|
|
/* 64 bit mask with bits [hi,...,lo] set. */
|
|
static inline uint64_t
|
|
mask64 (int hi, int lo)
|
|
{
|
|
int nbits = (hi + 1) - lo;
|
|
return ((1L << nbits) - 1) << lo;
|
|
}
|
|
|
|
/* Pick bits [hi,...,lo] from val. */
|
|
static inline uint32_t
|
|
pick32 (uint32_t val, int hi, int lo)
|
|
{
|
|
return val & mask32 (hi, lo);
|
|
}
|
|
|
|
/* Pick bits [hi,...,lo] from val. */
|
|
static inline uint64_t
|
|
pick64 (uint64_t val, int hi, int lo)
|
|
{
|
|
return val & mask64 (hi, lo);
|
|
}
|
|
|
|
/* Pick bits [hi,...,lo] from val and shift to [(hi-(newlo - lo)),newlo]. */
|
|
static inline uint32_t
|
|
pickshift32 (uint32_t val, int hi, int lo, int newlo)
|
|
{
|
|
uint32_t bits = pick32 (val, hi, lo);
|
|
|
|
if (lo < newlo)
|
|
return bits << (newlo - lo);
|
|
|
|
return bits >> (lo - newlo);
|
|
}
|
|
|
|
/* Mask [hi,lo] and shift down to start at bit 0. */
|
|
static inline uint32_t
|
|
pickbits32 (uint32_t val, int hi, int lo)
|
|
{
|
|
return pick32 (val, hi, lo) >> lo;
|
|
}
|
|
|
|
/* Mask [hi,lo] and shift down to start at bit 0. */
|
|
static inline uint64_t
|
|
pickbits64 (uint64_t val, int hi, int lo)
|
|
{
|
|
return pick64 (val, hi, lo) >> lo;
|
|
}
|
|
|
|
/* Decode registers, immediates and constants of various types. */
|
|
|
|
static inline GReg
|
|
greg (uint32_t val, int lo)
|
|
{
|
|
return (GReg) pickbits32 (val, lo + 4, lo);
|
|
}
|
|
|
|
static inline VReg
|
|
vreg (uint32_t val, int lo)
|
|
{
|
|
return (VReg) pickbits32 (val, lo + 4, lo);
|
|
}
|
|
|
|
static inline uint32_t
|
|
uimm (uint32_t val, int hi, int lo)
|
|
{
|
|
return pickbits32 (val, hi, lo);
|
|
}
|
|
|
|
static inline int32_t
|
|
simm32 (uint32_t val, int hi, int lo)
|
|
{
|
|
union
|
|
{
|
|
uint32_t u;
|
|
int32_t n;
|
|
} x;
|
|
|
|
x.u = val << (31 - hi);
|
|
return x.n >> (31 - hi + lo);
|
|
}
|
|
|
|
static inline int64_t
|
|
simm64 (uint64_t val, int hi, int lo)
|
|
{
|
|
union
|
|
{
|
|
uint64_t u;
|
|
int64_t n;
|
|
} x;
|
|
|
|
x.u = val << (63 - hi);
|
|
return x.n >> (63 - hi + lo);
|
|
}
|
|
|
|
static inline Shift
|
|
shift (uint32_t val, int lo)
|
|
{
|
|
return (Shift) pickbits32 (val, lo + 1, lo);
|
|
}
|
|
|
|
static inline Extension
|
|
extension (uint32_t val, int lo)
|
|
{
|
|
return (Extension) pickbits32 (val, lo + 2, lo);
|
|
}
|
|
|
|
static inline Scaling
|
|
scaling (uint32_t val, int lo)
|
|
{
|
|
return (Scaling) pickbits32 (val, lo, lo);
|
|
}
|
|
|
|
static inline WriteBack
|
|
writeback (uint32_t val, int lo)
|
|
{
|
|
return (WriteBack) pickbits32 (val, lo, lo);
|
|
}
|
|
|
|
static inline CondCode
|
|
condcode (uint32_t val, int lo)
|
|
{
|
|
return (CondCode) pickbits32 (val, lo + 3, lo);
|
|
}
|
|
|
|
/* Operation decode.
|
|
Bits [28,24] are the primary dispatch vector. */
|
|
|
|
static inline uint32_t
|
|
dispatchGroup (uint32_t val)
|
|
{
|
|
return pickshift32 (val, 28, 25, 0);
|
|
}
|
|
|
|
/* The 16 possible values for bits [28,25] identified by tags which
|
|
map them to the 5 main instruction groups LDST, DPREG, ADVSIMD,
|
|
BREXSYS and DPIMM.
|
|
|
|
An extra group PSEUDO is included in one of the unallocated ranges
|
|
for simulator-specific pseudo-instructions. */
|
|
|
|
enum DispatchGroup
|
|
{
|
|
GROUP_PSEUDO_0000,
|
|
GROUP_UNALLOC_0001,
|
|
GROUP_UNALLOC_0010,
|
|
GROUP_UNALLOC_0011,
|
|
GROUP_LDST_0100,
|
|
GROUP_DPREG_0101,
|
|
GROUP_LDST_0110,
|
|
GROUP_ADVSIMD_0111,
|
|
GROUP_DPIMM_1000,
|
|
GROUP_DPIMM_1001,
|
|
GROUP_BREXSYS_1010,
|
|
GROUP_BREXSYS_1011,
|
|
GROUP_LDST_1100,
|
|
GROUP_DPREG_1101,
|
|
GROUP_LDST_1110,
|
|
GROUP_ADVSIMD_1111
|
|
};
|
|
|
|
/* Bits [31, 29] of a Pseudo are the secondary dispatch vector. */
|
|
|
|
static inline uint32_t
|
|
dispatchPseudo (uint32_t val)
|
|
{
|
|
return pickshift32 (val, 31, 29, 0);
|
|
}
|
|
|
|
/* The 8 possible values for bits [31,29] in a Pseudo Instruction.
|
|
Bits [28,25] are always 0000. */
|
|
|
|
enum DispatchPseudo
|
|
{
|
|
PSEUDO_UNALLOC_000, /* Unallocated. */
|
|
PSEUDO_UNALLOC_001, /* Ditto. */
|
|
PSEUDO_UNALLOC_010, /* Ditto. */
|
|
PSEUDO_UNALLOC_011, /* Ditto. */
|
|
PSEUDO_UNALLOC_100, /* Ditto. */
|
|
PSEUDO_UNALLOC_101, /* Ditto. */
|
|
PSEUDO_CALLOUT_110, /* CALLOUT -- bits [24,0] identify call/ret sig. */
|
|
PSEUDO_HALT_111 /* HALT -- bits [24, 0] identify halt code. */
|
|
};
|
|
|
|
/* Bits [25, 23] of a DPImm are the secondary dispatch vector. */
|
|
|
|
static inline uint32_t
|
|
dispatchDPImm (uint32_t instr)
|
|
{
|
|
return pickshift32 (instr, 25, 23, 0);
|
|
}
|
|
|
|
/* The 8 possible values for bits [25,23] in a Data Processing Immediate
|
|
Instruction. Bits [28,25] are always 100_. */
|
|
|
|
enum DispatchDPImm
|
|
{
|
|
DPIMM_PCADR_000, /* PC-rel-addressing. */
|
|
DPIMM_PCADR_001, /* Ditto. */
|
|
DPIMM_ADDSUB_010, /* Add/Subtract (immediate). */
|
|
DPIMM_ADDSUB_011, /* Ditto. */
|
|
DPIMM_LOG_100, /* Logical (immediate). */
|
|
DPIMM_MOV_101, /* Move Wide (immediate). */
|
|
DPIMM_BITF_110, /* Bitfield. */
|
|
DPIMM_EXTR_111 /* Extract. */
|
|
};
|
|
|
|
/* Bits [29,28:26] of a LS are the secondary dispatch vector. */
|
|
|
|
static inline uint32_t
|
|
dispatchLS (uint32_t instr)
|
|
{
|
|
return ( pickshift32 (instr, 29, 28, 1)
|
|
| pickshift32 (instr, 26, 26, 0));
|
|
}
|
|
|
|
/* The 8 possible values for bits [29,28:26] in a Load/Store
|
|
Instruction. Bits [28,25] are always _1_0. */
|
|
|
|
enum DispatchLS
|
|
{
|
|
LS_EXCL_000, /* Load/store exclusive (includes some unallocated). */
|
|
LS_ADVSIMD_001, /* AdvSIMD load/store (various -- includes some unallocated). */
|
|
LS_LIT_010, /* Load register literal (includes some unallocated). */
|
|
LS_LIT_011, /* Ditto. */
|
|
LS_PAIR_100, /* Load/store register pair (various). */
|
|
LS_PAIR_101, /* Ditto. */
|
|
LS_OTHER_110, /* Other load/store formats. */
|
|
LS_OTHER_111 /* Ditto. */
|
|
};
|
|
|
|
/* Bits [28:24:21] of a DPReg are the secondary dispatch vector. */
|
|
|
|
static inline uint32_t
|
|
dispatchDPReg (uint32_t instr)
|
|
{
|
|
return ( pickshift32 (instr, 28, 28, 2)
|
|
| pickshift32 (instr, 24, 24, 1)
|
|
| pickshift32 (instr, 21, 21, 0));
|
|
}
|
|
|
|
/* The 8 possible values for bits [28:24:21] in a Data Processing
|
|
Register Instruction. Bits [28,25] are always _101. */
|
|
|
|
enum DispatchDPReg
|
|
{
|
|
DPREG_LOG_000, /* Logical (shifted register). */
|
|
DPREG_LOG_001, /* Ditto. */
|
|
DPREG_ADDSHF_010, /* Add/subtract (shifted register). */
|
|
DPREG_ADDEXT_011, /* Add/subtract (extended register). */
|
|
DPREG_ADDCOND_100, /* Add/subtract (with carry) AND
|
|
Cond compare/select AND
|
|
Data Processing (1/2 source). */
|
|
DPREG_UNALLOC_101, /* Unallocated. */
|
|
DPREG_3SRC_110, /* Data Processing (3 source). */
|
|
DPREG_3SRC_111 /* Data Processing (3 source). */
|
|
};
|
|
|
|
/* bits [31,29] of a BrExSys are the secondary dispatch vector. */
|
|
|
|
static inline uint32_t
|
|
dispatchBrExSys (uint32_t instr)
|
|
{
|
|
return pickbits32 (instr, 31, 29);
|
|
}
|
|
|
|
/* The 8 possible values for bits [31,29] in a Branch/Exception/System
|
|
Instruction. Bits [28,25] are always 101_. */
|
|
|
|
enum DispatchBr
|
|
{
|
|
BR_IMM_000, /* Unconditional branch (immediate). */
|
|
BR_IMMCMP_001, /* Compare & branch (immediate) AND
|
|
Test & branch (immediate). */
|
|
BR_IMMCOND_010, /* Conditional branch (immediate) AND Unallocated. */
|
|
BR_UNALLOC_011, /* Unallocated. */
|
|
BR_IMM_100, /* Unconditional branch (immediate). */
|
|
BR_IMMCMP_101, /* Compare & branch (immediate) AND
|
|
Test & branch (immediate). */
|
|
BR_REG_110, /* Unconditional branch (register) AND System AND
|
|
Excn gen AND Unallocated. */
|
|
BR_UNALLOC_111 /* Unallocated. */
|
|
};
|
|
|
|
/* TODO still need to provide secondary decode and dispatch for
|
|
AdvSIMD Insructions with instr[28,25] = 0111 or 1111. */
|
|
|
|
#endif /* _DECODE_H */
|