aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog6
-rw-r--r--gas/config/tc-ppc.c37
-rw-r--r--opcodes/ChangeLog14
-rw-r--r--opcodes/ppc-opc.c199
4 files changed, 101 insertions, 155 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 2773d92..601f2aa 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,11 @@
2018-11-06 Alan Modra <amodra@gmail.com>
+ * config/tc-ppc.c (insn_validate): Don't ignore mask in
+ PPC_OPSHIFT_INV case. Call the insert function to calculate
+ a mask.
+
+2018-11-06 Alan Modra <amodra@gmail.com>
+
* config/tc-ppc.c (insn_validate): Check that optional operands
are not followed by non-optional operands.
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 694c47a..9a06668 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -1522,23 +1522,32 @@ insn_validate (const struct powerpc_opcode *op)
}
else
{
+ uint64_t mask;
const struct powerpc_operand *operand = &powerpc_operands[*o];
- if (operand->shift != (int) PPC_OPSHIFT_INV)
+ if (operand->shift == (int) PPC_OPSHIFT_INV)
{
- uint64_t mask;
-
- if (operand->shift >= 0)
- mask = operand->bitm << operand->shift;
- else
- mask = operand->bitm >> -operand->shift;
- if (omask & mask)
- {
- as_bad (_("operand %d overlap in %s"),
- (int) (o - op->operands), op->name);
- return TRUE;
- }
- omask |= mask;
+ const char *errmsg;
+ int64_t val;
+
+ errmsg = NULL;
+ val = -1;
+ if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+ val = -val;
+ else if ((operand->flags & PPC_OPERAND_PLUS1) != 0)
+ val += 1;
+ mask = (*operand->insert) (0, val, ppc_cpu, &errmsg);
+ }
+ else if (operand->shift >= 0)
+ mask = operand->bitm << operand->shift;
+ else
+ mask = operand->bitm >> -operand->shift;
+ if (omask & mask)
+ {
+ as_bad (_("operand %d overlap in %s"),
+ (int) (o - op->operands), op->name);
+ return TRUE;
}
+ omask |= mask;
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
optional = TRUE;
else if (optional)
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index ce55624..5af52e6 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,17 @@
+2018-11-06 Alan Modra <amodra@gmail.com>
+
+ * ppc-opc.c (insert_arx, insert_ary, insert_rx, insert_ry, insert_ls),
+ (insert_evuimm1_ex0, insert_evuimm2_ex0, insert_evuimm4_ex0),
+ (insert_evuimm8_ex0, insert_evuimm_lt8, insert_evuimm_lt16),
+ (insert_rD_rS_even, insert_off_lsp, insert_off_spe2, insert_Ddd):
+ Don't return zero on error, insert mask bits instead.
+ (insert_sd4h, extract_sd4h, insert_sd4w, extract_sd4w): Delete.
+ (insert_sh6, extract_sh6): Delete dead code.
+ (insert_sprbat, insert_sprg): Use unsigned comparisions.
+ (powerpc_operands <OIMM>): Set shift count rather than using
+ PPC_OPSHIFT_INV.
+ <SE_SDH, SE_SDW>: Likewise. Don't use insert/extract functions.
+
2018-11-06 Jan Beulich <jbeulich@suse.com>
* i386-dis-evex.h (evex_table): Use K suffix instead of %LW for
diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c
index e303efa..bb31164 100644
--- a/opcodes/ppc-opc.c
+++ b/opcodes/ppc-opc.c
@@ -45,13 +45,13 @@ insert_arx (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg ATTRIBUTE_UNUSED)
{
- if (value >= 8 && value < 24)
- return insn | ((value - 8) & 0xf);
- else
+ value -= 8;
+ if (value < 0 || value >= 16)
{
*errmsg = _("invalid register");
- return 0;
+ value = 0xf;
}
+ return insn | value;
}
static int64_t
@@ -68,13 +68,13 @@ insert_ary (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg ATTRIBUTE_UNUSED)
{
- if (value >= 8 && value < 24)
- return insn | (((value - 8) & 0xf) << 4);
- else
+ value -= 8;
+ if (value < 0 || value >= 16)
{
*errmsg = _("invalid register");
- return 0;
+ value = 0xf;
}
+ return insn | (value << 4);
}
static int64_t
@@ -92,14 +92,15 @@ insert_rx (uint64_t insn,
const char **errmsg)
{
if (value >= 0 && value < 8)
- return insn | value;
+ ;
else if (value >= 24 && value <= 31)
- return insn | (value - 16);
+ value -= 16;
else
{
*errmsg = _("invalid register");
- return 0;
+ value = 0xf;
}
+ return insn | value;
}
static int64_t
@@ -121,14 +122,15 @@ insert_ry (uint64_t insn,
const char **errmsg)
{
if (value >= 0 && value < 8)
- return insn | (value << 4);
+ ;
else if (value >= 24 && value <= 31)
- return insn | ((value - 16) << 4);
+ value -= 16;
else
{
*errmsg = _("invalid register");
- return 0;
+ value = 0xf;
}
+ return insn | (value << 4);
}
static int64_t
@@ -601,10 +603,7 @@ insert_ls (uint64_t insn,
{
int64_t max_lvalue = (dialect & PPC_OPCODE_POWER4) ? 2 : 1;
if (value > max_lvalue)
- {
- *errmsg = _("illegal L operand value");
- return insn;
- }
+ *errmsg = _("illegal L operand value");
}
return insn | ((value & 0x3) << 21);
@@ -1086,40 +1085,6 @@ extract_sci8n (uint64_t insn,
}
static uint64_t
-insert_sd4h (uint64_t insn,
- int64_t value,
- ppc_cpu_t dialect ATTRIBUTE_UNUSED,
- const char **errmsg ATTRIBUTE_UNUSED)
-{
- return insn | ((value & 0x1e) << 7);
-}
-
-static int64_t
-extract_sd4h (uint64_t insn,
- ppc_cpu_t dialect ATTRIBUTE_UNUSED,
- int *invalid ATTRIBUTE_UNUSED)
-{
- return ((insn >> 8) & 0xf) << 1;
-}
-
-static uint64_t
-insert_sd4w (uint64_t insn,
- int64_t value,
- ppc_cpu_t dialect ATTRIBUTE_UNUSED,
- const char **errmsg ATTRIBUTE_UNUSED)
-{
- return insn | ((value & 0x3c) << 6);
-}
-
-static int64_t
-extract_sd4w (uint64_t insn,
- ppc_cpu_t dialect ATTRIBUTE_UNUSED,
- int *invalid ATTRIBUTE_UNUSED)
-{
- return ((insn >> 8) & 0xf) << 2;
-}
-
-static uint64_t
insert_oimm (uint64_t insn,
int64_t value,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
@@ -1144,11 +1109,7 @@ insert_sh6 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg ATTRIBUTE_UNUSED)
{
- /* SH6 operand in the rldixor instructions. */
- if (PPC_OP (insn) == 4)
- return insn | ((value & 0x1f) << 6) | ((value & 0x20) >> 5);
- else
- return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
+ return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
}
static int64_t
@@ -1156,11 +1117,7 @@ extract_sh6 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
int *invalid ATTRIBUTE_UNUSED)
{
- /* SH6 operand in the rldixor instructions. */
- if (PPC_OP (insn) == 4)
- return ((insn >> 6) & 0x1f) | ((insn << 5) & 0x20);
- else
- return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
+ return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
}
/* The SPR field in an XFX form instruction. This is flipped--the
@@ -1192,12 +1149,12 @@ insert_sprbat (uint64_t insn,
ppc_cpu_t dialect,
const char **errmsg)
{
- if (value > 7
- || (value > 3 && (dialect & ALLOW8_BAT) == 0))
+ if ((uint64_t) value > 7
+ || ((uint64_t) value > 3 && (dialect & ALLOW8_BAT) == 0))
*errmsg = _("invalid bat number");
/* If this is [di]bat4..7 then use spr 560..575, otherwise 528..543. */
- if (value > 3)
+ if ((uint64_t) value > 3)
value = ((value & 3) << 6) | 1;
else
value = value << 6;
@@ -1227,13 +1184,13 @@ insert_sprg (uint64_t insn,
ppc_cpu_t dialect,
const char **errmsg)
{
- if (value > 7
- || (value > 3 && (dialect & ALLOW8_SPRG) == 0))
+ if ((uint64_t) value > 7
+ || ((uint64_t) value > 3 && (dialect & ALLOW8_SPRG) == 0))
*errmsg = _("invalid sprg number");
/* If this is mfsprg4..7 then use spr 260..263 which can be read in
user mode. Anything else must use spr 272..279. */
- if (value <= 3 || (insn & 0x100) != 0)
+ if ((uint64_t) value <= 3 || (insn & 0x100) != 0)
value |= 0x10;
return insn | ((value & 0x17) << 16);
@@ -1513,13 +1470,9 @@ insert_evuimm1_ex0 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value > 0 && value <= 0x1f)
- return insn | ((value & 0x1f) << 11);
- else
- {
- *errmsg = _("UIMM = 00000 is illegal");
- return 0;
- }
+ if (value <= 0 || value > 0x1f)
+ *errmsg = _("UIMM = 00000 is illegal");
+ return insn | ((value & 0x1f) << 11);
}
static int64_t
@@ -1540,13 +1493,9 @@ insert_evuimm2_ex0 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value > 0 && value <= 0x3e)
- return insn | ((value & 0x3e) << 10);
- else
- {
- *errmsg = _("UIMM = 00000 is illegal");
- return 0;
- }
+ if (value <= 0 || value > 0x3e)
+ *errmsg = _("UIMM = 00000 is illegal");
+ return insn | ((value & 0x3e) << 10);
}
static int64_t
@@ -1567,13 +1516,9 @@ insert_evuimm4_ex0 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value > 0 && value <= 0x7c)
- return insn | ((value & 0x7c) << 9);
- else
- {
- *errmsg = _("UIMM = 00000 is illegal");
- return 0;
- }
+ if (value <= 0 || value > 0x7c)
+ *errmsg = _("UIMM = 00000 is illegal");
+ return insn | ((value & 0x7c) << 9);
}
static int64_t
@@ -1594,13 +1539,9 @@ insert_evuimm8_ex0 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value > 0 && value <= 0xf8)
- return insn | ((value & 0xf8) << 8);
- else
- {
- *errmsg = _("UIMM = 00000 is illegal");
- return 0;
- }
+ if (value <= 0 || value > 0xf8)
+ *errmsg = _("UIMM = 00000 is illegal");
+ return insn | ((value & 0xf8) << 8);
}
static int64_t
@@ -1621,13 +1562,9 @@ insert_evuimm_lt8 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value >= 0 && value <= 7)
- return insn | ((value & 0x7) << 11);
- else
- {
- *errmsg = _("UIMM values >7 are illegal");
- return 0;
- }
+ if (value < 0 || value > 7)
+ *errmsg = _("UIMM values >7 are illegal");
+ return insn | ((value & 0x7) << 11);
}
static int64_t
@@ -1648,13 +1585,9 @@ insert_evuimm_lt16 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value >= 0 && value <= 15)
- return insn | ((value & 0xf) << 11);
- else
- {
- *errmsg = _("UIMM values >15 are illegal");
- return 0;
- }
+ if (value < 0 || value > 15)
+ *errmsg = _("UIMM values >15 are illegal");
+ return insn | ((value & 0xf) << 11);
}
static int64_t
@@ -1675,13 +1608,9 @@ insert_rD_rS_even (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if ((value & 0x1) == 0)
- return insn | ((value & 0x1e) << 21);
- else
- {
- *errmsg = _("GPR odd is illegal");
- return 0;
- }
+ if ((value & 0x1) != 0)
+ *errmsg = _("GPR odd is illegal");
+ return insn | ((value & 0x1e) << 21);
}
static int64_t
@@ -1702,13 +1631,9 @@ insert_off_lsp (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value > 0 && value <= 0x3)
- return insn | (value & 0x3);
- else
- {
- *errmsg = _("invalid offset");
- return 0;
- }
+ if (value <= 0 || value > 0x3)
+ *errmsg = _("invalid offset");
+ return insn | (value & 0x3);
}
static int64_t
@@ -1729,13 +1654,9 @@ insert_off_spe2 (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value > 0 && value <= 0x7)
- return insn | (value & 0x7);
- else
- {
- *errmsg = _("invalid offset");
- return 0;
- }
+ if (value <= 0 || value > 0x7)
+ *errmsg = _("invalid offset");
+ return insn | (value & 0x7);
}
static int64_t
@@ -1756,13 +1677,9 @@ insert_Ddd (uint64_t insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
- if (value >= 0 && value <= 0x7)
- return insn | ((value & 0x3) << 11) | ((value & 0x4) >> 2);
- else
- {
- *errmsg = _("invalid Ddd value");
- return 0;
- }
+ if (value < 0 || value > 0x7)
+ *errmsg = _("invalid Ddd value");
+ return insn | ((value & 0x3) << 11) | ((value & 0x4) >> 2);
}
static int64_t
@@ -2296,11 +2213,11 @@ const struct powerpc_operand powerpc_operands[] =
/* The SD field of the SD4 form instruction, for halfword. */
#define SE_SDH SE_SD + 1
- { 0x1e, PPC_OPSHIFT_INV, insert_sd4h, extract_sd4h, PPC_OPERAND_PARENS },
+ { 0x1e, 7, NULL, NULL, PPC_OPERAND_PARENS },
/* The SD field of the SD4 form instruction, for word. */
#define SE_SDW SE_SDH + 1
- { 0x3c, PPC_OPSHIFT_INV, insert_sd4w, extract_sd4w, PPC_OPERAND_PARENS },
+ { 0x3c, 6, NULL, NULL, PPC_OPERAND_PARENS },
/* The SH field in an X or M form instruction. */
#define SH SE_SDW + 1
@@ -2414,7 +2331,7 @@ const struct powerpc_operand powerpc_operands[] =
/* The OIMM field in an SE_OIM5 instruction. */
#define OIMM5 UI5 + 1
- { 0x1f, PPC_OPSHIFT_INV, insert_oimm, extract_oimm, PPC_OPERAND_PLUS1 },
+ { 0x1f, 4, insert_oimm, extract_oimm, PPC_OPERAND_PLUS1 },
/* The UI7 field in an SE_LI instruction. */
#define UI7 OIMM5 + 1