| 1 | /* cr16-opc.c -- Table of opcodes for the CR16 processor. |
| 2 | Copyright (C) 2007-2015 Free Software Foundation, Inc. |
| 3 | Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com) |
| 4 | |
| 5 | This file is part of the GNU opcodes library. |
| 6 | |
| 7 | This library is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 3, or (at your option) |
| 10 | any later version. |
| 11 | |
| 12 | It is distributed in the hope that it will be useful, but WITHOUT |
| 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| 14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
| 15 | License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with this program; if not, write to the Free Software Foundation, |
| 19 | Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ |
| 20 | |
| 21 | #include <stdio.h> |
| 22 | #include "libiberty.h" |
| 23 | #include "symcat.h" |
| 24 | #include "opcode/cr16.h" |
| 25 | |
| 26 | const inst cr16_instruction[] = |
| 27 | { |
| 28 | /* Create an arithmetic instruction - INST[bw]. */ |
| 29 | #define ARITH_BYTE_INST(NAME, OPC, OP1) \ |
| 30 | /* opc8 imm4 r */ \ |
| 31 | {NAME, 1, OPC, 24, ARITH_BYTE_INS, {{uimm4_1,20}, {regr,16}}}, \ |
| 32 | /* opc8 imm16 r */ \ |
| 33 | {NAME, 2, (OPC<<4)+0xB, 20, ARITH_BYTE_INS, {{OP1,0}, {regr,16}}}, \ |
| 34 | /* opc8 r r */ \ |
| 35 | {NAME, 1, OPC+0x1, 24, ARITH_BYTE_INS, {{regr,20}, {regr,16}}} |
| 36 | |
| 37 | /* For Logical operations, allow unsigned imm16 also. */ |
| 38 | #define ARITH1_BYTE_INST(NAME, OPC, OP1) \ |
| 39 | /* opc8 imm16 r */ \ |
| 40 | {NAME, 2, (OPC<<4)+0xB, 20, ARITH_BYTE_INS, {{OP1,0}, {regr,16}}} |
| 41 | |
| 42 | |
| 43 | ARITH_BYTE_INST ("andb", 0x20, uimm16), |
| 44 | ARITH1_BYTE_INST ("andb", 0x20, imm16), |
| 45 | ARITH_BYTE_INST ("andw", 0x22, uimm16), |
| 46 | ARITH1_BYTE_INST ("andw", 0x22, imm16), |
| 47 | |
| 48 | ARITH_BYTE_INST ("orb", 0x24, uimm16), |
| 49 | ARITH1_BYTE_INST ("orb", 0x24, imm16), |
| 50 | ARITH_BYTE_INST ("orw", 0x26, uimm16), |
| 51 | ARITH1_BYTE_INST ("orw", 0x26, imm16), |
| 52 | |
| 53 | ARITH_BYTE_INST ("xorb", 0x28, uimm16), |
| 54 | ARITH1_BYTE_INST ("xorb", 0x28, imm16), |
| 55 | ARITH_BYTE_INST ("xorw", 0x2A, uimm16), |
| 56 | ARITH1_BYTE_INST ("xorw", 0x2A, imm16), |
| 57 | |
| 58 | ARITH_BYTE_INST ("addub", 0x2C, imm16), |
| 59 | ARITH_BYTE_INST ("adduw", 0x2E, imm16), |
| 60 | ARITH_BYTE_INST ("addb", 0x30, imm16), |
| 61 | ARITH_BYTE_INST ("addw", 0x32, imm16), |
| 62 | ARITH_BYTE_INST ("addcb", 0x34, imm16), |
| 63 | ARITH_BYTE_INST ("addcw", 0x36, imm16), |
| 64 | |
| 65 | ARITH_BYTE_INST ("subb", 0x38, imm16), |
| 66 | ARITH_BYTE_INST ("subw", 0x3A, imm16), |
| 67 | ARITH_BYTE_INST ("subcb", 0x3C, imm16), |
| 68 | ARITH_BYTE_INST ("subcw", 0x3E, imm16), |
| 69 | |
| 70 | ARITH_BYTE_INST ("cmpb", 0x50, imm16), |
| 71 | ARITH_BYTE_INST ("cmpw", 0x52, imm16), |
| 72 | |
| 73 | ARITH_BYTE_INST ("movb", 0x58, imm16), |
| 74 | ARITH_BYTE_INST ("movw", 0x5A, imm16), |
| 75 | |
| 76 | ARITH_BYTE_INST ("mulb", 0x64, imm16), |
| 77 | ARITH_BYTE_INST ("mulw", 0x66, imm16), |
| 78 | |
| 79 | #define ARITH_BYTE_INST1(NAME, OPC) \ |
| 80 | /* opc8 r r */ \ |
| 81 | {NAME, 1, OPC, 24, ARITH_BYTE_INS, {{regr,20}, {regr,16}}} |
| 82 | |
| 83 | ARITH_BYTE_INST1 ("movxb", 0x5C), |
| 84 | ARITH_BYTE_INST1 ("movzb", 0x5D), |
| 85 | ARITH_BYTE_INST1 ("mulsb", 0x0B), |
| 86 | |
| 87 | #define ARITH_BYTE_INST2(NAME, OPC) \ |
| 88 | /* opc8 r rp */ \ |
| 89 | {NAME, 1, OPC, 24, ARITH_BYTE_INS, {{regr,20}, {regp,16}}} |
| 90 | |
| 91 | ARITH_BYTE_INST2 ("movxw", 0x5E), |
| 92 | ARITH_BYTE_INST2 ("movzw", 0x5F), |
| 93 | ARITH_BYTE_INST2 ("mulsw", 0x62), |
| 94 | ARITH_BYTE_INST2 ("muluw", 0x63), |
| 95 | |
| 96 | /* Create an arithmetic instruction - INST[d]- with 3 types. */ |
| 97 | #define ARITH_INST_D(NAME, OPC) \ |
| 98 | /* opc8 imm4 rp */ \ |
| 99 | {NAME, 1, OPC, 24, ARITH_INS, {{uimm4_1,20}, {regp,16}}}, \ |
| 100 | /* opc8 imm16 rp */ \ |
| 101 | {NAME, 2, (OPC<<4)+0xB, 20, ARITH_INS, {{imm16,0}, {regp,16}}}, \ |
| 102 | /* opc8 rp rp */ \ |
| 103 | {NAME, 1, OPC+1, 24, ARITH_INS, {{regp,20}, {regp,16}}} |
| 104 | |
| 105 | /* Create an arithmetic instruction - INST[d]-20 bit types. */ |
| 106 | #define ARITH_INST20(NAME, OPC) \ |
| 107 | /* opc8 uimm20 rp */ \ |
| 108 | {NAME, 2, OPC, 24, ARITH_INS, {{uimm20,0}, {regp,20}}} |
| 109 | |
| 110 | /* Create an arithmetic instruction - INST[d]-32 bit types. */ |
| 111 | #define ARITH_INST32(NAME, OPC, OP1) \ |
| 112 | /* opc12 imm32 rp */ \ |
| 113 | {NAME, 3, OPC, 20, ARITH_INS, {{OP1,0}, {regp,16}}} |
| 114 | |
| 115 | /* Create an arithmetic instruction - INST[d]-32bit types(reg pairs).*/ |
| 116 | #define ARITH_INST32RP(NAME, OPC) \ |
| 117 | /* opc24 rp rp */ \ |
| 118 | {NAME, 2, OPC, 12, ARITH_INS, {{regp,4}, {regp,0}}} |
| 119 | |
| 120 | ARITH_INST_D ("movd", 0x54), |
| 121 | ARITH_INST20 ("movd", 0x05), |
| 122 | ARITH_INST32 ("movd", 0x007, imm32), |
| 123 | ARITH_INST_D ("addd", 0x60), |
| 124 | ARITH_INST20 ("addd", 0x04), |
| 125 | ARITH_INST32 ("addd", 0x002, imm32), |
| 126 | ARITH_INST32 ("subd", 0x003, imm32), |
| 127 | ARITH_INST32RP ("subd", 0x0014C), |
| 128 | ARITH_INST_D ("cmpd", 0x56), |
| 129 | ARITH_INST32 ("cmpd", 0x009, imm32), |
| 130 | ARITH_INST32 ("andd", 0x004, uimm32), |
| 131 | ARITH_INST32RP ("andd", 0x0014B), |
| 132 | ARITH_INST32 ("ord", 0x005, uimm32), |
| 133 | ARITH_INST32RP ("ord", 0x00149), |
| 134 | ARITH_INST32 ("xord", 0x006, uimm32), |
| 135 | ARITH_INST32RP ("xord", 0x0014A), |
| 136 | |
| 137 | /* Create a shift instruction. */ |
| 138 | #define SHIFT_INST_A(NAME, OPC1, OPC2, SHIFT, OP1, OP2) \ |
| 139 | /* opc imm r */ \ |
| 140 | {NAME, 1, OPC1, SHIFT, SHIFT_INS, {{OP1,20}, {OP2,16}}}, \ |
| 141 | /* opc imm r */ \ |
| 142 | {NAME, 1, OPC1+1, SHIFT, SHIFT_INS, {{OP1,20}, {OP2,16}}},\ |
| 143 | /* opc r r */ \ |
| 144 | {NAME, 1, OPC2, 24, SHIFT_INS, {{regr,20}, {OP2,16}}} |
| 145 | |
| 146 | SHIFT_INST_A("ashub", 0x80, 0x41, 23, imm4, regr), |
| 147 | SHIFT_INST_A("ashud", 0x26, 0x48, 25, imm6, regp), |
| 148 | SHIFT_INST_A("ashuw", 0x42, 0x45, 24, imm5, regr), |
| 149 | |
| 150 | #define SHIFT_INST_L(NAME, OPC1, OPC2, SHIFT, OP1, OP2) \ |
| 151 | /* opc imm r */ \ |
| 152 | {NAME, 1, OPC1, SHIFT, SHIFT_INS, {{OP1,20}, {OP2,16}}}, \ |
| 153 | /* opc r r */ \ |
| 154 | {NAME, 1, OPC2, 24, SHIFT_INS, {{regr,20}, {OP2,16}}} |
| 155 | |
| 156 | SHIFT_INST_L("lshb", 0x13, 0x44, 23, imm4, regr), |
| 157 | SHIFT_INST_L("lshd", 0x25, 0x47, 25, imm6, regp), |
| 158 | SHIFT_INST_L("lshw", 0x49, 0x46, 24, imm5, regr), |
| 159 | |
| 160 | /* Create a conditional branch instruction. */ |
| 161 | #define BRANCH_INST(NAME, OPC) \ |
| 162 | /* opc4 c4 dispe9 */ \ |
| 163 | {NAME, 1, OPC, 28, BRANCH_INS | RELAXABLE, {{cc,20}, {dispe9,16}}},\ |
| 164 | /* opc4 c4 disps17 */ \ |
| 165 | {NAME, 2, ((OPC<<4)+0x8), 24, BRANCH_INS | RELAXABLE, {{cc,20}, {disps17,0}}},\ |
| 166 | /* opc4 c4 disps25 */ \ |
| 167 | {NAME, 3, (OPC<<4), 16 , BRANCH_INS | RELAXABLE, {{cc,4}, {disps25,16}}} |
| 168 | |
| 169 | BRANCH_INST ("b", 0x1), |
| 170 | |
| 171 | /* Create a 'Branch if Equal to 0' instruction. */ |
| 172 | #define BRANCH_NEQ_INST(NAME, OPC) \ |
| 173 | /* opc8 disps5 r */ \ |
| 174 | {NAME, 1, OPC, 24, BRANCH_NEQ_INS, {{regr,16}, {disps5,20}}} |
| 175 | |
| 176 | BRANCH_NEQ_INST ("beq0b", 0x0C), |
| 177 | BRANCH_NEQ_INST ("bne0b", 0x0D), |
| 178 | BRANCH_NEQ_INST ("beq0w", 0x0E), |
| 179 | BRANCH_NEQ_INST ("bne0w", 0x0F), |
| 180 | |
| 181 | |
| 182 | /* Create an instruction using a single register operand. */ |
| 183 | #define REG1_INST(NAME, OPC) \ |
| 184 | /* opc8 c4 r */ \ |
| 185 | {NAME, 1, OPC, 20, NO_TYPE_INS, {{regr,16}}} |
| 186 | |
| 187 | #define REGP1_INST(NAME, OPC) \ |
| 188 | /* opc8 c4 r */ \ |
| 189 | {NAME, 1, OPC, 20, NO_TYPE_INS, {{regp,16}}} |
| 190 | |
| 191 | /* Same as REG1_INST, with additional FLAGS. */ |
| 192 | #define REG1_FLAG_INST(NAME, OPC, FLAGS) \ |
| 193 | /* opc8 c4 r */ \ |
| 194 | {NAME, 1, OPC, 20, NO_TYPE_INS | FLAGS, {{regp,16}}} |
| 195 | |
| 196 | /* JCond instructions */ |
| 197 | REGP1_INST ("jeq", 0x0A0), |
| 198 | REGP1_INST ("jne", 0x0A1), |
| 199 | REGP1_INST ("jcs", 0x0A2), |
| 200 | REGP1_INST ("jcc", 0x0A3), |
| 201 | REGP1_INST ("jhi", 0x0A4), |
| 202 | REGP1_INST ("jls", 0x0A5), |
| 203 | REGP1_INST ("jgt", 0x0A6), |
| 204 | REGP1_INST ("jle", 0x0A7), |
| 205 | REGP1_INST ("jfs", 0x0A8), |
| 206 | REGP1_INST ("jfc", 0x0A9), |
| 207 | REGP1_INST ("jlo", 0x0AA), |
| 208 | REGP1_INST ("jhs", 0x0AB), |
| 209 | REGP1_INST ("jlt", 0x0AC), |
| 210 | REGP1_INST ("jge", 0x0AD), |
| 211 | REGP1_INST ("jump", 0x0AE), |
| 212 | REGP1_INST ("jusr", 0x0AF), |
| 213 | |
| 214 | /* SCond instructions */ |
| 215 | REG1_INST ("seq", 0x080), |
| 216 | REG1_INST ("sne", 0x081), |
| 217 | REG1_INST ("scs", 0x082), |
| 218 | REG1_INST ("scc", 0x083), |
| 219 | REG1_INST ("shi", 0x084), |
| 220 | REG1_INST ("sls", 0x085), |
| 221 | REG1_INST ("sgt", 0x086), |
| 222 | REG1_INST ("sle", 0x087), |
| 223 | REG1_INST ("sfs", 0x088), |
| 224 | REG1_INST ("sfc", 0x089), |
| 225 | REG1_INST ("slo", 0x08A), |
| 226 | REG1_INST ("shs", 0x08B), |
| 227 | REG1_INST ("slt", 0x08C), |
| 228 | REG1_INST ("sge", 0x08D), |
| 229 | |
| 230 | |
| 231 | /* Create an instruction using two register operands. */ |
| 232 | #define REG3_INST(NAME, OPC) \ |
| 233 | /* opc24 r r rp */ \ |
| 234 | {NAME, 2, OPC, 12, NO_TYPE_INS, {{regr,4}, {regr,0}, {regp,8}}} |
| 235 | |
| 236 | /* MULTIPLY INSTRUCTIONS */ |
| 237 | REG3_INST ("macqw", 0x0014d), |
| 238 | REG3_INST ("macuw", 0x0014e), |
| 239 | REG3_INST ("macsw", 0x0014f), |
| 240 | |
| 241 | /* Create a branch instruction. */ |
| 242 | #define BR_INST(NAME, OPC) \ |
| 243 | /* opc12 ra disps25 */ \ |
| 244 | {NAME, 2, OPC, 24, NO_TYPE_INS, {{rra,0}, {disps25,0}}} |
| 245 | |
| 246 | #define BR_INST_RP(NAME, OPC) \ |
| 247 | /* opc8 rp disps25 */ \ |
| 248 | {NAME, 3, OPC, 12, NO_TYPE_INS, {{regp,4}, {disps25,16}}} |
| 249 | |
| 250 | BR_INST ("bal", 0xC0), |
| 251 | BR_INST_RP ("bal", 0x00102), |
| 252 | |
| 253 | #define REGPP2_INST(NAME, OPC) \ |
| 254 | /* opc16 rp rp */ \ |
| 255 | {NAME, 2, OPC, 12, NO_TYPE_INS, {{regp,0}, {regp,4}}} |
| 256 | /* Jump and link instructions. */ |
| 257 | REGP1_INST ("jal",0x00D), |
| 258 | REGPP2_INST ("jal",0x00148), |
| 259 | |
| 260 | |
| 261 | /* Instructions including a register list (opcode is represented as a mask). */ |
| 262 | #define REGLIST_INST(NAME, OPC, TYPE) \ |
| 263 | /* opc7 r count3 RA */ \ |
| 264 | {NAME,1, (OPC<<1)+1, 23, TYPE, {{uimm3_1,20},{regr,16},{regr,0}}}, \ |
| 265 | /* opc8 r count3 */ \ |
| 266 | {NAME, 1, OPC, 24, TYPE, {{uimm3_1,20}, {regr,16}}}, \ |
| 267 | /* opc12 RA */ \ |
| 268 | {NAME, 1, (OPC<<8)+0x1E, 16, TYPE, {{regr,0}}} |
| 269 | |
| 270 | REGLIST_INST ("push", 0x01, (NO_TYPE_INS | REG_LIST)), |
| 271 | REGLIST_INST ("pop", 0x02, (NO_TYPE_INS | REG_LIST)), |
| 272 | REGLIST_INST ("popret", 0x03, (NO_TYPE_INS | REG_LIST)), |
| 273 | |
| 274 | {"loadm", 1, 0x14, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}}, |
| 275 | {"loadmp", 1, 0x15, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}}, |
| 276 | {"storm", 1, 0x16, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}}, |
| 277 | {"stormp", 1, 0x17, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}}, |
| 278 | |
| 279 | /* Processor Regsiter Manipulation instructions */ |
| 280 | /* opc16 reg, preg */ |
| 281 | {"lpr", 2, 0x00140, 12, NO_TYPE_INS, {{regr,0}, {pregr,4}}}, |
| 282 | /* opc16 regp, pregp */ |
| 283 | {"lprd", 2, 0x00141, 12, NO_TYPE_INS, {{regp,0}, {pregrp,4}}}, |
| 284 | /* opc16 preg, reg */ |
| 285 | {"spr", 2, 0x00142, 12, NO_TYPE_INS, {{pregr,4}, {regr,0}}}, |
| 286 | /* opc16 pregp, regp */ |
| 287 | {"sprd", 2, 0x00143, 12, NO_TYPE_INS, {{pregrp,4}, {regp,0}}}, |
| 288 | |
| 289 | /* Miscellaneous. */ |
| 290 | /* opc12 ui4 */ |
| 291 | {"excp", 1, 0x00C, 20, NO_TYPE_INS, {{uimm4,16}}}, |
| 292 | |
| 293 | /* Create a bit-b instruction. */ |
| 294 | #define CSTBIT_INST_B(NAME, OP, OPC1, OPC2, OPC3, OPC4) \ |
| 295 | /* opcNN iN abs20 */ \ |
| 296 | {NAME, 2, (OPC3+1), 23, CSTBIT_INS, {{OP,20},{abs20,0}}}, \ |
| 297 | /* opcNN iN abs24 */ \ |
| 298 | {NAME, 3, (OPC2+3), 12, CSTBIT_INS, {{OP,4},{abs24,16}}}, \ |
| 299 | /* opcNN iN (Rindex)abs20 */ \ |
| 300 | {NAME, 2, OPC1, 24, CSTBIT_INS, {{OP,20}, {rindex7_abs20,0}}}, \ |
| 301 | /* opcNN iN (prp) disps14(RPbase) */ \ |
| 302 | {NAME, 2, OPC4, 22, CSTBIT_INS, {{OP,4},{rpindex_disps14,0}}}, \ |
| 303 | /* opcNN iN disps20(Rbase) */ \ |
| 304 | {NAME, 3, OPC2, 12, CSTBIT_INS, {{OP,4}, {rbase_disps20,16}}}, \ |
| 305 | /* opcNN iN (rp) disps0(RPbase) */ \ |
| 306 | {NAME, 1, OPC3-2, 23, CSTBIT_INS, {{OP,20}, {rpbase_disps0,16}}}, \ |
| 307 | /* opcNN iN (rp) disps16(RPBase) */ \ |
| 308 | {NAME, 2, OPC3, 23, CSTBIT_INS, {{OP,20}, {rpbase_disps16,0}}}, \ |
| 309 | /* opcNN iN (rp) disps20(RPBase) */ \ |
| 310 | {NAME, 3, (OPC2+1), 12, CSTBIT_INS, {{OP,4}, {rpbase_disps20,16}}}, \ |
| 311 | /* opcNN iN rrp (Rindex)disps20(RPbase) */ \ |
| 312 | {NAME, 3, (OPC2+2), 12, CSTBIT_INS, {{OP,4}, {rpindex_disps20,16}}} |
| 313 | |
| 314 | CSTBIT_INST_B ("cbitb", uimm3, 0x68, 0x00104, 0xD6, 0x1AA), |
| 315 | CSTBIT_INST_B ("sbitb", uimm3, 0x70, 0x00108, 0xE6, 0x1CA), |
| 316 | CSTBIT_INST_B ("tbitb", uimm3, 0x78, 0x0010C, 0xF6, 0x1EA), |
| 317 | |
| 318 | /* Create a bit-w instruction. */ |
| 319 | #define CSTBIT_INST_W(NAME, OP, OPC1, OPC2, OPC3, OPC4) \ |
| 320 | /* opcNN iN abs20 */ \ |
| 321 | {NAME, 2, OPC1+6, 24, CSTBIT_INS, {{OP,20},{abs20,0}}}, \ |
| 322 | /* opcNN iN abs24 */ \ |
| 323 | {NAME, 3, OPC2+3, 12, CSTBIT_INS, {{OP,4},{abs24,16}}}, \ |
| 324 | /* opcNN iN (Rindex)abs20 */ \ |
| 325 | {NAME, 2, OPC3, 25, CSTBIT_INS, {{OP,20}, {rindex8_abs20,0}}}, \ |
| 326 | /* opcNN iN (prp) disps14(RPbase) */ \ |
| 327 | {NAME, 2, OPC4, 22, CSTBIT_INS, {{OP,4},{rpindex_disps14,0}}}, \ |
| 328 | /* opcNN iN disps20(Rbase) */ \ |
| 329 | {NAME, 3, OPC2, 12, CSTBIT_INS, {{OP,4}, {rbase_disps20,16}}}, \ |
| 330 | /* opcNN iN (rp) disps0(RPbase) */ \ |
| 331 | {NAME, 1, OPC1+5, 24, CSTBIT_INS, {{OP,20}, {rpbase_disps0,16}}}, \ |
| 332 | /* opcNN iN (rp) disps16(RPBase) */ \ |
| 333 | {NAME, 2, OPC1, 24, CSTBIT_INS, {{OP,20}, {rpbase_disps16,0}}}, \ |
| 334 | /* opcNN iN (rp) disps20(RPBase) */ \ |
| 335 | {NAME, 3, OPC2+1, 12, CSTBIT_INS, {{OP,4}, {rpbase_disps20,16}}}, \ |
| 336 | /* opcNN iN rrp (Rindex)disps20(RPbase) */ \ |
| 337 | {NAME, 3, OPC2+2, 12, CSTBIT_INS, {{OP,4}, {rpindex_disps20,16}}} |
| 338 | |
| 339 | CSTBIT_INST_W ("cbitw", uimm4, 0x69, 0x00114, 0x36, 0x1AB), |
| 340 | CSTBIT_INST_W ("sbitw", uimm4, 0x71, 0x00118, 0x3A, 0x1CB), |
| 341 | CSTBIT_INST_W ("tbitw", uimm4, 0x79, 0x0011C, 0x3E, 0x1EB), |
| 342 | |
| 343 | /* tbit cnt */ |
| 344 | {"tbit", 1, 0x06, 24, CSTBIT_INS, {{uimm4,20}, {regr,16}}}, |
| 345 | /* tbit reg reg */ |
| 346 | {"tbit", 1, 0x07, 24, CSTBIT_INS, {{regr,20}, {regr,16}}}, |
| 347 | |
| 348 | |
| 349 | /* Load instructions (from memory to register). */ |
| 350 | #define LD_REG_INST(NAME, OPC1, OPC2, OPC3, OPC4, OPC5, OP_S, OP_D) \ |
| 351 | /* opc8 reg abs20 */ \ |
| 352 | {NAME, 2, OPC3, 24, LD_STOR_INS, {{abs20,0}, {OP_D,20}}}, \ |
| 353 | /* opc20 reg abs24 */ \ |
| 354 | {NAME, 3, OPC1+3, 12, LD_STOR_INS, {{abs24,16}, {OP_D,4}}}, \ |
| 355 | /* opc7 reg rindex8_abs20 */ \ |
| 356 | {NAME, 2, OPC5, 25, LD_STOR_INS, {{rindex8_abs20,0}, {OP_D,20}}}, \ |
| 357 | /* opc4 reg disps4(RPbase) */ \ |
| 358 | {NAME, 1, (OPC2>>4), 28, LD_STOR_INS, {{OP_S,24}, {OP_D,20}}}, \ |
| 359 | /* opcNN reg disps0(RPbase) */ \ |
| 360 | {NAME, 1, OPC2, 24, LD_STOR_INS, {{rpindex_disps0,0}, {OP_D,20}}}, \ |
| 361 | /* opc reg disps14(RPbase) */ \ |
| 362 | {NAME, 2, OPC4, 22, LD_STOR_INS, {{rpindex_disps14,0}, {OP_D,20}}}, \ |
| 363 | /* opc reg -disps20(Rbase) */ \ |
| 364 | {NAME, 3, OPC1+0x60, 12, LD_STOR_INS, {{rbase_dispe20,16}, {OP_D,4}}}, \ |
| 365 | /* opc reg disps20(Rbase) */ \ |
| 366 | {NAME, 3, OPC1, 12, LD_STOR_INS, {{rbase_disps20,16}, {OP_D,4}}}, \ |
| 367 | /* opc reg (rp) disps16(RPbase) */ \ |
| 368 | {NAME, 2, OPC2+1, 24, LD_STOR_INS, {{rpbase_disps16,0}, {OP_D,20}}}, \ |
| 369 | /* opc16 reg (rp) disps20(RPbase) */ \ |
| 370 | {NAME, 3, OPC1+1, 12, LD_STOR_INS, {{rpbase_disps20,16}, {OP_D,4}}}, \ |
| 371 | /* op reg (rp) -disps20(RPbase) */ \ |
| 372 | {NAME, 3, OPC1+0x61, 12, LD_STOR_INS, {{rpbase_dispe20,16}, {OP_D,4}}}, \ |
| 373 | /* opc reg rrp (Rindex)disps20(RPbase) */ \ |
| 374 | {NAME, 3, (OPC1+2), 12, LD_STOR_INS, {{rpindex_disps20,16}, {OP_D,4}}} |
| 375 | |
| 376 | LD_REG_INST ("loadb", 0x00124, 0xBE, 0x88, 0x219, 0x45, rpbase_disps4, regr), |
| 377 | LD_REG_INST ("loadd", 0x00128, 0xAE, 0x87, 0x21A, 0x46, rpbase_dispe4, regp), |
| 378 | LD_REG_INST ("loadw", 0x0012C, 0x9E, 0x89, 0x21B, 0x47, rpbase_dispe4, regr), |
| 379 | |
| 380 | /* Store instructions (from reg to memory). */ |
| 381 | #define ST_REG_INST(NAME, OPC1, OPC2, OPC3, OPC4, OPC5, OP_D, OP_S) \ |
| 382 | /* opc8 reg abs20 */ \ |
| 383 | {NAME, 2, OPC3, 24, LD_STOR_INS, {{OP_S,20}, {abs20,0}}}, \ |
| 384 | /* opc20 reg abs24 */ \ |
| 385 | {NAME, 3, OPC1+3, 12, LD_STOR_INS, {{OP_S,4}, {abs24,16}}}, \ |
| 386 | /* opc7 reg rindex8_abs20 */ \ |
| 387 | {NAME, 2, OPC5, 25, LD_STOR_INS, {{OP_S,20}, {rindex8_abs20,0}}}, \ |
| 388 | /* opc4 reg disps4(RPbase) */ \ |
| 389 | {NAME, 1, (OPC2>>4), 28, LD_STOR_INS, {{OP_S,20}, {OP_D,24}}}, \ |
| 390 | /* opcNN reg disps0(RPbase) */ \ |
| 391 | {NAME, 1, OPC2, 24, LD_STOR_INS, {{OP_S,20}, {rpindex_disps0,0}}}, \ |
| 392 | /* opc reg disps14(RPbase) */ \ |
| 393 | {NAME, 2, OPC4, 22, LD_STOR_INS, {{OP_S,20}, {rpindex_disps14,0}}}, \ |
| 394 | /* opc reg -disps20(Rbase) */ \ |
| 395 | {NAME, 3, OPC1+0x60, 12, LD_STOR_INS, {{OP_S,4}, {rbase_dispe20,16}}}, \ |
| 396 | /* opc reg disps20(Rbase) */ \ |
| 397 | {NAME, 3, OPC1, 12, LD_STOR_INS, {{OP_S,4}, {rbase_disps20,16}}}, \ |
| 398 | /* opc reg disps16(RPbase) */ \ |
| 399 | {NAME, 2, OPC2+1, 24, LD_STOR_INS, {{OP_S,20}, {rpbase_disps16,0}}}, \ |
| 400 | /* opc16 reg disps20(RPbase) */ \ |
| 401 | {NAME, 3, OPC1+1, 12, LD_STOR_INS, {{OP_S,4}, {rpbase_disps20,16}}}, \ |
| 402 | /* op reg (rp) -disps20(RPbase) */ \ |
| 403 | {NAME, 3, OPC1+0x61, 12, LD_STOR_INS, {{OP_S,4}, {rpbase_dispe20,16}}}, \ |
| 404 | /* opc reg rrp (Rindex)disps20(RPbase) */ \ |
| 405 | {NAME, 3, OPC1+2, 12, LD_STOR_INS, {{OP_S,4}, {rpindex_disps20,16}}} |
| 406 | |
| 407 | |
| 408 | /* Store instructions (from imm to memory). */ |
| 409 | #define ST_IMM_INST(NAME, OPC1, OPC2, OPC3, OPC4) \ |
| 410 | /* opcNN iN abs20 */ \ |
| 411 | {NAME, 2, OPC1, 24, LD_STOR_INS, {{uimm4,20},{abs20,0}}}, \ |
| 412 | /* opcNN iN abs24 */ \ |
| 413 | {NAME, 3, OPC2+3, 12, LD_STOR_INS, {{uimm4,4},{abs24,16}}}, \ |
| 414 | /* opcNN iN (Rindex)abs20 */ \ |
| 415 | {NAME, 2, OPC3, 25, LD_STOR_INS, {{uimm4,20}, {rindex8_abs20,0}}}, \ |
| 416 | /* opcNN iN (prp) disps14(RPbase) */ \ |
| 417 | {NAME, 2, OPC4, 22, LD_STOR_INS, {{uimm4,4},{rpindex_disps14,0}}}, \ |
| 418 | /* opcNN iN (rp) disps0(RPbase) */ \ |
| 419 | {NAME, 1, OPC1+1, 24, LD_STOR_INS, {{uimm4,20}, {rpbase_disps0,16}}}, \ |
| 420 | /* opcNN iN disps20(Rbase) */ \ |
| 421 | {NAME, 3, OPC2, 12, LD_STOR_INS, {{uimm4,4}, {rbase_disps20,16}}}, \ |
| 422 | /* opcNN iN (rp) disps16(RPBase) */ \ |
| 423 | {NAME, 2, OPC1+2, 24, LD_STOR_INS, {{uimm4,20}, {rpbase_disps16,0}}}, \ |
| 424 | /* opcNN iN (rp) disps20(RPBase) */ \ |
| 425 | {NAME, 3, OPC2+1, 12, LD_STOR_INS, {{uimm4,4}, {rpbase_disps20,16}}}, \ |
| 426 | /* opcNN iN rrp (Rindex)disps20(RPbase) */ \ |
| 427 | {NAME, 3, OPC2+2, 12, LD_STOR_INS, {{uimm4,4}, {rpindex_disps20,16}}} |
| 428 | |
| 429 | ST_REG_INST ("storb", 0x00134, 0xFE, 0xC8, 0x319, 0x65, rpbase_disps4, regr), |
| 430 | ST_IMM_INST ("storb", 0x81, 0x00120, 0x42, 0x218), |
| 431 | ST_REG_INST ("stord", 0x00138, 0xEE, 0xC7, 0x31A, 0x66, rpbase_dispe4, regp), |
| 432 | ST_REG_INST ("storw", 0x0013C, 0xDE, 0xC9, 0x31B, 0x67, rpbase_dispe4, regr), |
| 433 | ST_IMM_INST ("storw", 0xC1, 0x00130, 0x62, 0x318), |
| 434 | |
| 435 | /* Create instruction with no operands. */ |
| 436 | #define NO_OP_INST(NAME, OPC) \ |
| 437 | /* opc16 */ \ |
| 438 | {NAME, 1, OPC, 16, 0, {{0, 0}}} |
| 439 | |
| 440 | NO_OP_INST ("cinv[i]", 0x000A), |
| 441 | NO_OP_INST ("cinv[i,u]", 0x000B), |
| 442 | NO_OP_INST ("cinv[d]", 0x000C), |
| 443 | NO_OP_INST ("cinv[d,u]", 0x000D), |
| 444 | NO_OP_INST ("cinv[d,i]", 0x000E), |
| 445 | NO_OP_INST ("cinv[d,i,u]", 0x000F), |
| 446 | NO_OP_INST ("nop", 0x2C00), |
| 447 | NO_OP_INST ("retx", 0x0003), |
| 448 | NO_OP_INST ("di", 0x0004), |
| 449 | NO_OP_INST ("ei", 0x0005), |
| 450 | NO_OP_INST ("wait", 0x0006), |
| 451 | NO_OP_INST ("eiwait", 0x0007), |
| 452 | |
| 453 | {NULL, 0, 0, 0, 0, {{0, 0}}} |
| 454 | }; |
| 455 | |
| 456 | const unsigned int cr16_num_opcodes = ARRAY_SIZE (cr16_instruction); |
| 457 | |
| 458 | /* Macro to build a reg_entry, which have an opcode image : |
| 459 | For example : |
| 460 | REG(u4, 0x84, CR16_U_REGTYPE) |
| 461 | is interpreted as : |
| 462 | {"u4", u4, 0x84, CR16_U_REGTYPE} |
| 463 | The union initializer (second member) always refers to the first |
| 464 | member of the union, so cast NAME to that type to avoid possible |
| 465 | compiler warnings when used for CR16_P_REGTYPE cases. */ |
| 466 | #define REG(NAME, N, TYPE) {STRINGX(NAME), {(reg) NAME}, N, TYPE} |
| 467 | |
| 468 | #define REGP(NAME, BNAME, N, TYPE) {STRINGX(NAME), {BNAME}, N, TYPE} |
| 469 | |
| 470 | const reg_entry cr16_regtab[] = |
| 471 | { /* Build a general purpose register r<N>. */ |
| 472 | #define REG_R(N) REG(CONCAT2(r,N), N, CR16_R_REGTYPE) |
| 473 | |
| 474 | REG_R(0), REG_R(1), REG_R(2), REG_R(3), |
| 475 | REG_R(4), REG_R(5), REG_R(6), REG_R(7), |
| 476 | REG_R(8), REG_R(9), REG_R(10), REG_R(11), |
| 477 | REG_R(12), REG_R(13), REG_R(14), REG_R(15), |
| 478 | REG(r12_L, 12, CR16_R_REGTYPE), |
| 479 | REG(r13_L, 13, CR16_R_REGTYPE), |
| 480 | REG(ra, 0xe, CR16_R_REGTYPE), |
| 481 | REG(sp, 0xf, CR16_R_REGTYPE), |
| 482 | REG(sp_L, 0xf, CR16_R_REGTYPE), |
| 483 | REG(RA, 0xe, CR16_R_REGTYPE), |
| 484 | }; |
| 485 | |
| 486 | const reg_entry cr16_regptab[] = |
| 487 | { /* Build a general purpose register r<N>. */ |
| 488 | |
| 489 | #define REG_RP(M,N) REGP((CONCAT2(r,M),CONCAT2(r,N)), CONCAT2(r,N), N, CR16_RP_REGTYPE) |
| 490 | |
| 491 | REG_RP(1,0), REG_RP(2,1), REG_RP(3,2), REG_RP(4,3), |
| 492 | REG_RP(5,4), REG_RP(6,5), REG_RP(7,6), REG_RP(8,7), |
| 493 | REG_RP(9,8), REG_RP(10,9), REG_RP(11,10), REG_RP(12,11), |
| 494 | REG((r12), 0xc, CR16_RP_REGTYPE), |
| 495 | REG((r13), 0xd, CR16_RP_REGTYPE), |
| 496 | //REG((r14), 0xe, CR16_RP_REGTYPE), |
| 497 | REG((ra), 0xe, CR16_RP_REGTYPE), |
| 498 | REG((sp), 0xf, CR16_RP_REGTYPE), |
| 499 | }; |
| 500 | |
| 501 | |
| 502 | const unsigned int cr16_num_regs = ARRAY_SIZE (cr16_regtab) ; |
| 503 | const unsigned int cr16_num_regps = ARRAY_SIZE (cr16_regptab) ; |
| 504 | |
| 505 | const reg_entry cr16_pregtab[] = |
| 506 | { |
| 507 | /* Build a processor register. */ |
| 508 | REG(dbs, 0x0, CR16_P_REGTYPE), |
| 509 | REG(dsr, 0x1, CR16_P_REGTYPE), |
| 510 | REG(dcrl, 0x2, CR16_P_REGTYPE), |
| 511 | REG(dcrh, 0x3, CR16_P_REGTYPE), |
| 512 | REG(car0l, 0x4, CR16_P_REGTYPE), |
| 513 | REG(car0h, 0x5, CR16_P_REGTYPE), |
| 514 | REG(car1l, 0x6, CR16_P_REGTYPE), |
| 515 | REG(car1h, 0x7, CR16_P_REGTYPE), |
| 516 | REG(cfg, 0x8, CR16_P_REGTYPE), |
| 517 | REG(psr, 0x9, CR16_P_REGTYPE), |
| 518 | REG(intbasel, 0xa, CR16_P_REGTYPE), |
| 519 | REG(intbaseh, 0xb, CR16_P_REGTYPE), |
| 520 | REG(ispl, 0xc, CR16_P_REGTYPE), |
| 521 | REG(isph, 0xd, CR16_P_REGTYPE), |
| 522 | REG(uspl, 0xe, CR16_P_REGTYPE), |
| 523 | REG(usph, 0xf, CR16_P_REGTYPE), |
| 524 | }; |
| 525 | |
| 526 | const reg_entry cr16_pregptab[] = |
| 527 | { |
| 528 | REG(dbs, 0, CR16_P_REGTYPE), |
| 529 | REG(dsr, 1, CR16_P_REGTYPE), |
| 530 | REG(dcr, 2, CR16_P_REGTYPE), |
| 531 | REG(car0, 4, CR16_P_REGTYPE), |
| 532 | REG(car1, 6, CR16_P_REGTYPE), |
| 533 | REG(cfg, 8, CR16_P_REGTYPE), |
| 534 | REG(psr, 9, CR16_P_REGTYPE), |
| 535 | REG(intbase, 10, CR16_P_REGTYPE), |
| 536 | REG(isp, 12, CR16_P_REGTYPE), |
| 537 | REG(usp, 14, CR16_P_REGTYPE), |
| 538 | }; |
| 539 | |
| 540 | const unsigned int cr16_num_pregs = ARRAY_SIZE (cr16_pregtab); |
| 541 | const unsigned int cr16_num_pregps = ARRAY_SIZE (cr16_pregptab); |
| 542 | |
| 543 | const char *cr16_b_cond_tab[]= |
| 544 | { |
| 545 | "eq","ne","cs","cc","hi","ls","gt","le","fs","fc", |
| 546 | "lo","hs","lt","ge","r", "???" |
| 547 | }; |
| 548 | |
| 549 | const unsigned int cr16_num_cc = ARRAY_SIZE (cr16_b_cond_tab); |
| 550 | |
| 551 | /* CR16 operands table. */ |
| 552 | const operand_entry cr16_optab[] = |
| 553 | { |
| 554 | /* Index 0 is dummy, so we can count the instruction's operands. */ |
| 555 | {0, nullargs, 0}, /* dummy */ |
| 556 | {3, arg_ic, OP_SIGNED}, /* imm3 */ |
| 557 | {4, arg_ic, OP_SIGNED}, /* imm4 */ |
| 558 | {5, arg_ic, OP_SIGNED}, /* imm5 */ |
| 559 | {6, arg_ic, OP_SIGNED}, /* imm6 */ |
| 560 | {16, arg_ic, OP_SIGNED}, /* imm16 */ |
| 561 | {20, arg_ic, OP_SIGNED}, /* imm20 */ |
| 562 | {32, arg_ic, OP_SIGNED}, /* imm32 */ |
| 563 | {3, arg_ic, OP_UNSIGNED}, /* uimm3 */ |
| 564 | {3, arg_ic, OP_UNSIGNED|OP_DEC}, /* uimm3_1 */ |
| 565 | {4, arg_ic, OP_UNSIGNED}, /* uimm4 */ |
| 566 | {4, arg_ic, OP_UNSIGNED|OP_ESC}, /* uimm4_1 */ |
| 567 | {5, arg_ic, OP_UNSIGNED}, /* uimm5 */ |
| 568 | {16, arg_ic, OP_UNSIGNED}, /* uimm16 */ |
| 569 | {20, arg_ic, OP_UNSIGNED}, /* uimm20 */ |
| 570 | {32, arg_ic, OP_UNSIGNED}, /* uimm32 */ |
| 571 | {5, arg_c, OP_EVEN|OP_SHIFT_DEC|OP_SIGNED}, /* disps5 */ |
| 572 | {16, arg_c, OP_EVEN|OP_UNSIGNED}, /* disps17 */ |
| 573 | {24, arg_c, OP_EVEN|OP_UNSIGNED}, /* disps25 */ |
| 574 | {8, arg_c, OP_EVEN|OP_UNSIGNED}, /* dispe9 */ |
| 575 | {20, arg_c, OP_UNSIGNED|OP_ABS20}, /* abs20 */ |
| 576 | {24, arg_c, OP_UNSIGNED|OP_ABS24}, /* abs24 */ |
| 577 | {4, arg_rp, 0}, /* rra */ |
| 578 | {4, arg_rbase, 0}, /* rbase */ |
| 579 | {20, arg_cr, OP_UNSIGNED}, /* rbase_disps20 */ |
| 580 | {21, arg_cr, OP_NEG}, /* rbase_dispe20 */ |
| 581 | {0, arg_crp, 0}, /* rpbase_disps0 */ |
| 582 | {4, arg_crp, OP_EVEN|OP_SHIFT|OP_UNSIGNED|OP_ESC1},/* rpbase_dispe4 */ |
| 583 | {4, arg_crp, OP_UNSIGNED|OP_ESC1}, /* rpbase_disps4 */ |
| 584 | {16, arg_crp, OP_UNSIGNED}, /* rpbase_disps16 */ |
| 585 | {20, arg_crp, OP_UNSIGNED}, /* rpbase_disps20 */ |
| 586 | {21, arg_crp, OP_NEG}, /* rpbase_dispe20 */ |
| 587 | {20, arg_idxr, OP_UNSIGNED}, /* rindex7_abs20 */ |
| 588 | {20, arg_idxr, OP_UNSIGNED}, /* rindex8_abs20 */ |
| 589 | {0, arg_idxrp, OP_UNSIGNED}, /* rpindex_disps0 */ |
| 590 | {14, arg_idxrp, OP_UNSIGNED}, /* rpindex_disps14 */ |
| 591 | {20, arg_idxrp, OP_UNSIGNED}, /* rpindex_disps20 */ |
| 592 | {4, arg_r, 0}, /* regr */ |
| 593 | {4, arg_rp, 0}, /* reg pair */ |
| 594 | {4, arg_pr, 0}, /* proc reg */ |
| 595 | {4, arg_prp, 0}, /* 32 bit proc reg */ |
| 596 | {4, arg_cc, OP_UNSIGNED} /* cc - code */ |
| 597 | }; |
| 598 | |
| 599 | const unsigned int cr16_num_optab = ARRAY_SIZE (cr16_optab); |
| 600 | |
| 601 | /* CR16 traps/interrupts. */ |
| 602 | const trap_entry cr16_traps[] = |
| 603 | { |
| 604 | {"svc", 5}, {"dvz", 6}, {"flg", 7}, {"bpt", 8}, {"trc", 9}, |
| 605 | {"und", 10}, {"iad", 12}, {"dbg",14}, {"ise",15} |
| 606 | }; |
| 607 | |
| 608 | const unsigned int cr16_num_traps = ARRAY_SIZE (cr16_traps); |
| 609 | |
| 610 | /* CR16 instructions that don't have arguments. */ |
| 611 | const char * cr16_no_op_insn[] = |
| 612 | { |
| 613 | "cinv[i]", "cinv[i,u]", "cinv[d]", "cinv[d,u]", "cinv[d,i]", "cinv[d,i,u]", |
| 614 | "di", "ei", "eiwait", "nop", "retx", "wait", NULL |
| 615 | }; |