| /* |
| * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. |
| * |
| * 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 2 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/>. |
| */ |
| |
| /* |
| * opcodes.c |
| * |
| * data tables generated automatically |
| * Maybe some functions too |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "attribs.h" |
| #include "decode.h" |
| |
| #define VEC_DESCR(A, B, C) DESCR(A, B, C) |
| #define DONAME(X) #X |
| |
| const char * const opcode_names[] = { |
| #define OPCODE(IID) DONAME(IID) |
| #include "opcodes_def_generated.h.inc" |
| NULL |
| #undef OPCODE |
| }; |
| |
| const char * const opcode_reginfo[] = { |
| #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ |
| #define REGINFO(TAG, REGINFO, RREGS, WREGS) REGINFO, |
| #include "op_regs_generated.h.inc" |
| NULL |
| #undef REGINFO |
| #undef IMMINFO |
| }; |
| |
| |
| const char * const opcode_rregs[] = { |
| #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ |
| #define REGINFO(TAG, REGINFO, RREGS, WREGS) RREGS, |
| #include "op_regs_generated.h.inc" |
| NULL |
| #undef REGINFO |
| #undef IMMINFO |
| }; |
| |
| |
| const char * const opcode_wregs[] = { |
| #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ |
| #define REGINFO(TAG, REGINFO, RREGS, WREGS) WREGS, |
| #include "op_regs_generated.h.inc" |
| NULL |
| #undef REGINFO |
| #undef IMMINFO |
| }; |
| |
| const char * const opcode_short_semantics[] = { |
| #define DEF_SHORTCODE(TAG, SHORTCODE) [TAG] = #SHORTCODE, |
| #include "shortcode_generated.h.inc" |
| #undef DEF_SHORTCODE |
| NULL |
| }; |
| |
| DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB); |
| |
| static void init_attribs(int tag, ...) |
| { |
| va_list ap; |
| int attr; |
| va_start(ap, tag); |
| while ((attr = va_arg(ap, int)) != 0) { |
| set_bit(attr, opcode_attribs[tag]); |
| } |
| va_end(ap); |
| } |
| |
| const OpcodeEncoding opcode_encodings[] = { |
| #define DEF_ENC32(OPCODE, ENCSTR) \ |
| [OPCODE] = { .encoding = ENCSTR }, |
| |
| #define DEF_ENC_SUBINSN(OPCODE, CLASS, ENCSTR) \ |
| [OPCODE] = { .encoding = ENCSTR, .enc_class = CLASS }, |
| |
| #define DEF_EXT_ENC(OPCODE, CLASS, ENCSTR) \ |
| [OPCODE] = { .encoding = ENCSTR, .enc_class = CLASS }, |
| |
| #include "imported/encode.def" |
| |
| #undef DEF_ENC32 |
| #undef DEF_ENC_SUBINSN |
| #undef DEF_EXT_ENC |
| }; |
| |
| void opcode_init(void) |
| { |
| init_attribs(0, 0); |
| |
| #define ATTRIBS(...) , ## __VA_ARGS__, 0 |
| #define OP_ATTRIB(TAG, ARGS) init_attribs(TAG ARGS); |
| #include "op_attribs_generated.h.inc" |
| #undef OP_ATTRIB |
| #undef ATTRIBS |
| |
| decode_init(); |
| } |
| |
| |
| #define NEEDLE "IMMEXT(" |
| |
| int opcode_which_immediate_is_extended(Opcode opcode) |
| { |
| const char *p; |
| |
| g_assert(opcode < XX_LAST_OPCODE); |
| g_assert(GET_ATTRIB(opcode, A_EXTENDABLE)); |
| |
| p = opcode_short_semantics[opcode]; |
| p = strstr(p, NEEDLE); |
| g_assert(p); |
| p += strlen(NEEDLE); |
| while (isspace(*p)) { |
| p++; |
| } |
| /* lower is always imm 0, upper always imm 1. */ |
| if (islower(*p)) { |
| return 0; |
| } else if (isupper(*p)) { |
| return 1; |
| } else { |
| g_assert_not_reached(); |
| } |
| } |