summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opcode-bitmask-gen.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/opcode-bitmask-gen.c b/opcode-bitmask-gen.c
index 3fe26fa..c4fa446 100644
--- a/opcode-bitmask-gen.c
+++ b/opcode-bitmask-gen.c
@@ -417,17 +417,25 @@ void set_extension(int *ext, int ext2, int force, const char *reason, ...) {
}
uint32_t get_addr_mode_bits(const char **list, int *ext) {
+ const uint32_t max_addr_mode_mask = -(uint32_t)1 >> (32-AMT_LEN);
uint32_t addr_modes = 0;
+ int is_ext = 0;
for (int i = 0; list[i] != NULL; ++i) {
- const char *str = list[i];
+ const int is_inv = (list[i][0] == '~');
+ const char *str = list[i]+is_inv;
+ const uint32_t ext_mask = (AM_ORTHO|AM_ORTHO2|AM_EIND|AM_EIND2|AM_AIND|AM_AINDX|AM_AINDY);
+ uint32_t bits = 0;
for (int j = 0; j < AMT_LEN; ++j) {
if (!strcasecmp(str, adrmode[j])) {
//printf("i: %i, str: %s, adrmode: %s\n", i, str, adrmode[i]);
- addr_modes |= (1 << j);
+ bits |= (1 << j);
}
}
+ is_ext = (bits & ext_mask) ? 1 : is_ext;
+ addr_modes |= (is_inv) ? ~(bits) & (max_addr_mode_mask & (is_ext) ? -1 : ~ext_mask) : bits;
+ addr_modes &= (is_ext && (bits & ~(AM_ORTHO|AM_ORTHO2))) ? ~(AM_ORTHO|AM_ORTHO2) : -1;
}
- if (addr_modes & (AM_ORTHO|AM_ORTHO2|AM_EIND|AM_EIND2|AM_AIND|AM_AINDX|AM_AINDY)) {
+ if (is_ext) {
const int ext2 = (addr_modes & AM_ORTHO) ? ORTHO : EXT;
const char *addr_mode_reason = (ext2 == ORTHO) ? "was set to ortho" : "is a base extension addressing mode";
set_extension(ext, ext2, 1, "The addressing mode %s.\n", addr_mode_reason);