diff options
Diffstat (limited to 'plugins/arm/v7/pseudo.c')
-rw-r--r-- | plugins/arm/v7/pseudo.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/plugins/arm/v7/pseudo.c b/plugins/arm/v7/pseudo.c index 4055040..e50da2d 100644 --- a/plugins/arm/v7/pseudo.c +++ b/plugins/arm/v7/pseudo.c @@ -24,6 +24,7 @@ #include "pseudo.h" +#include <assert.h> #include <stddef.h> @@ -470,6 +471,126 @@ bool armv7_thumb_expand_imm(uint32_t imm12, uint32_t *value) /****************************************************************************** * * +* Paramètres : op = encodage d'opération. * +* cmode = détails quant au mode d'opération. * +* imm8 = valeur sur 8 bits à étendre. * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'AdvSIMDExpandImm'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_advanced_simd_expand_imm(bool op, uint8_t cmode, uint8_t imm8, uint64_t *value) +{ + bool result; /* Bilan à retourner */ + uint64_t raw; /* Valeur d'entrée sur 64 bits */ + uint8_t cmode_31; /* Partie d'argument ciblée */ + uint64_t imm8a; /* Valeur sur 8 bits #1 */ + uint64_t imm8b; /* Valeur sur 8 bits #2 */ + uint64_t imm8c; /* Valeur sur 8 bits #3 */ + uint64_t imm8d; /* Valeur sur 8 bits #4 */ + uint64_t imm8e; /* Valeur sur 8 bits #5 */ + uint64_t imm8f; /* Valeur sur 8 bits #6 */ + uint64_t imm8g; /* Valeur sur 8 bits #7 */ + uint64_t imm8h; /* Valeur sur 8 bits #8 */ + uint32_t imm32; /* Valeur sur 32 bits */ + + result = true; + + raw = imm8; + + cmode_31 = (cmode >> 1) & 0x7; + + switch (cmode_31) + { + case b000: + *value = armv7_replicate_64(raw, 2); + break; + + case b001: + *value = armv7_replicate_64(raw << 8, 2); + break; + + case b010: + *value = armv7_replicate_64(raw << 16, 2); + break; + + case b011: + *value = armv7_replicate_64(raw << 24, 2); + break; + + case b100: + *value = armv7_replicate_64(raw, 4); + break; + + case b101: + *value = armv7_replicate_64(raw << 8, 4); + break; + + case b110: + + if ((cmode & 0x1) == 0) + *value = armv7_replicate_64(raw << 8 | 0xff, 2); + else + *value = armv7_replicate_64(raw << 16 | 0xffff, 2); + break; + + case b111: + + if ((cmode & 0x1) == 0) + { + if (!op) + *value = armv7_replicate_64(raw, 8); + + else + { + imm8a = armv7_replicate_8((imm8 & 0x80) >> 7, 8); + imm8b = armv7_replicate_8((imm8 & 0x40) >> 6, 8); + imm8c = armv7_replicate_8((imm8 & 0x20) >> 5, 8); + imm8d = armv7_replicate_8((imm8 & 0x10) >> 4, 8); + imm8e = armv7_replicate_8((imm8 & 0x8) >> 3, 8); + imm8f = armv7_replicate_8((imm8 & 0x4) >> 2, 8); + imm8g = armv7_replicate_8((imm8 & 0x2) >> 1, 8); + imm8h = armv7_replicate_8((imm8 & 0x1) >> 0, 8); + + *value = (imm8a << 56) | (imm8b << 48) | (imm8c << 40) | (imm8d << 32) \ + | (imm8e << 24) | (imm8f << 16) | (imm8g << 8) | imm8h; + + } + + } + else + { + if (!op) + { + imm32 = (raw & 0x80) << 31 \ + | ((uint64_t)(raw & 0x40 ? 0 : 1)) << 30 \ + | armv7_replicate_8((raw & 0x40) >> 6, 5) \ + | ((raw & 0x3f) << 19); + + *value = armv7_replicate_64(imm32, 2); + + } + + else + result = false; + + } + break; + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : type2 = type de décalage encodé sur 2 bits. * * imm5 = valeur de décalage entière sur 5 bits. * * type = type de décalage à constituer. [OUT] * @@ -664,6 +785,72 @@ bool armv7_shift(uint32_t x, unsigned int n, SRType type, unsigned int amount, b /****************************************************************************** * * +* Paramètres : x = valeur sur 8 bits à traiter. * +* n = nombre de partie à recopier. * +* * +* Description : Constitue une value à partir de réplications. * +* * +* Retour : Nouvelle valeur calculée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint8_t armv7_replicate_8(uint8_t x, unsigned int n) +{ + uint8_t result; /* Value à retourner */ + unsigned int step; /* Marge de progression */ + unsigned int i; /* Boucle de parcours */ + + assert(8 % n == 0); + + result = 0; + + step = 8 / n; + + for (i = 0; i < 8; i += step) + result |= (x << (i * step)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 64 bits à traiter. * +* n = nombre de partie à recopier. * +* * +* Description : Constitue une value à partir de réplications. * +* * +* Retour : Nouvelle valeur calculée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint64_t armv7_replicate_64(uint64_t x, unsigned int n) +{ + uint64_t result; /* Value à retourner */ + unsigned int step; /* Marge de progression */ + unsigned int i; /* Boucle de parcours */ + + assert(64 % n == 0); + + result = 0; + + step = 64 / n; + + for (i = 0; i < 64; i += step) + result |= (x << (i * step)); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : x = valeur sur 32 bits maximum à traiter. * * n = nombre de bits à prendre en compte. * * i = taille finale à obtenir. * |