diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2018-02-06 14:43:07 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2018-02-06 14:43:07 -0800 |
commit | a7ecf2646d6c80b994be7d340140379d580050cf (patch) | |
tree | 50fc3d8fb36d4a96dff236ddaf2ee8420f27f020 /asm/directiv.c | |
parent | 4d7e680cb015e5d77764ff1cc83a417ecb73e31b (diff) | |
download | nasm-a7ecf2646d6c80b994be7d340140379d580050cf.tar.gz |
iflag: automatically assign values, saner handling of CPU levels
Automatically assign values to the instruction flags; we ended up with
a case where pushing flags into the next dword caused comparison
failures due to other places in the code explicitly comparing
field[3].
This creates necessary defines for this not to happen; it also cleans
up a fair bit of the iflag code.
This resolves BR 3392454.
Reported-by: Thomasz Kantecki <tomasz.kantecki@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'asm/directiv.c')
-rw-r--r-- | asm/directiv.c | 122 |
1 files changed, 67 insertions, 55 deletions
diff --git a/asm/directiv.c b/asm/directiv.c index 354b591a..4c30323a 100644 --- a/asm/directiv.c +++ b/asm/directiv.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 1996-2017 The NASM Authors - All Rights Reserved + * Copyright 1996-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -55,78 +55,90 @@ #include "labels.h" #include "iflag.h" -static iflag_t get_cpu(char *value) +struct cpunames { + const char *name; + unsigned int level; + /* Eventually a table of features */ +}; + +static iflag_t get_cpu(const char *value) { iflag_t r; + const struct cpunames *cpu; + static const struct cpunames cpunames[] = { + { "8086", IF_8086 }, + { "186", IF_186 }, + { "286", IF_286 }, + { "386", IF_386 }, + { "486", IF_486 }, + { "586", IF_PENT }, + { "pentium", IF_PENT }, + { "pentiummmx", IF_PENT }, + { "686", IF_P6 }, + { "p6", IF_P6 }, + { "ppro", IF_P6 }, + { "pentiumpro", IF_P6 }, + { "p2", IF_P6 }, /* +MMX */ + { "pentiumii", IF_P6 }, + { "p3", IF_KATMAI }, + { "katmai", IF_KATMAI }, + { "p4", IF_WILLAMETTE }, + { "willamette", IF_WILLAMETTE }, + { "prescott", IF_PRESCOTT }, + { "x64", IF_X86_64 }, + { "x86-64", IF_X86_64 }, + { "ia64", IF_IA64 }, + { "ia-64", IF_IA64 }, + { "itanium", IF_IA64 }, + { "itanic", IF_IA64 }, + { "merced", IF_IA64 }, + { "any", IF_PLEVEL }, + { "default", IF_PLEVEL }, + { "all", IF_PLEVEL }, + { NULL, IF_PLEVEL } /* Error and final default entry */ + }; + + for (cpu = cpunames; cpu->name; cpu++) { + if (!strcmp(value, cpu->name)) + break; + } - iflag_clear_all(&r); - - if (!strcmp(value, "8086")) - iflag_set(&r, IF_8086); - else if (!strcmp(value, "186")) - iflag_set(&r, IF_186); - else if (!strcmp(value, "286")) - iflag_set(&r, IF_286); - else if (!strcmp(value, "386")) - iflag_set(&r, IF_386); - else if (!strcmp(value, "486")) - iflag_set(&r, IF_486); - else if (!strcmp(value, "586") || - !nasm_stricmp(value, "pentium")) - iflag_set(&r, IF_PENT); - else if (!strcmp(value, "686") || - !nasm_stricmp(value, "ppro") || - !nasm_stricmp(value, "pentiumpro") || - !nasm_stricmp(value, "p2")) - iflag_set(&r, IF_P6); - else if (!nasm_stricmp(value, "p3") || - !nasm_stricmp(value, "katmai")) - iflag_set(&r, IF_KATMAI); - else if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */ - !nasm_stricmp(value, "willamette")) - iflag_set(&r, IF_WILLAMETTE); - else if (!nasm_stricmp(value, "prescott")) - iflag_set(&r, IF_PRESCOTT); - else if (!nasm_stricmp(value, "x64") || - !nasm_stricmp(value, "x86-64")) - iflag_set(&r, IF_X86_64); - else if (!nasm_stricmp(value, "ia64") || - !nasm_stricmp(value, "ia-64") || - !nasm_stricmp(value, "itanium")|| - !nasm_stricmp(value, "itanic") || - !nasm_stricmp(value, "merced")) - iflag_set(&r, IF_IA64); - else { - iflag_set(&r, IF_PLEVEL); + if (!cpu->name) { nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL, - "unknown 'cpu' type"); + "unknown 'cpu' type '%s'", value); } + + iflag_set_cpu(&r, cpu->level); return r; } -static int get_bits(char *value) +static int get_bits(const char *value) { - int i; + int i = atoi(value); - if ((i = atoi(value)) == 16) - return i; /* set for a 16-bit segment */ - else if (i == 32) { - if (iflag_ffs(&cpu) < IF_386) { + switch (i) { + case 16: + break; /* Always safe */ + case 32: + if (!iflag_cpu_level_ok(&cpu, IF_386)) { nasm_error(ERR_NONFATAL, - "cannot specify 32-bit segment on processor below a 386"); + "cannot specify 32-bit segment on processor below a 386"); i = 16; } - } else if (i == 64) { - if (iflag_ffs(&cpu) < IF_X86_64) { + break; + case 64: + if (!iflag_cpu_level_ok(&cpu, IF_X86_64)) { nasm_error(ERR_NONFATAL, - "cannot specify 64-bit segment on processor below an x86-64"); + "cannot specify 64-bit segment on processor below an x86-64"); i = 16; } - } else { + break; + default: nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL, - "`%s' is not a valid segment size; must be 16, 32 or 64", - value); + "`%s' is not a valid segment size; must be 16, 32 or 64", + value); i = 16; + break; } return i; } |