summaryrefslogtreecommitdiffstats
path: root/src/coff/base/gpdis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/coff/base/gpdis.cpp')
-rw-r--r--src/coff/base/gpdis.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/src/coff/base/gpdis.cpp b/src/coff/base/gpdis.cpp
new file mode 100644
index 0000000..2df4f24
--- /dev/null
+++ b/src/coff/base/gpdis.cpp
@@ -0,0 +1,349 @@
+/* Disassemble memory
+ Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Craig Franklin
+
+This file is part of gputils.
+
+gputils 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, or (at your option)
+any later version.
+
+gputils 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 gputils; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include <assert.h>
+#include "devices/pic/base/pic.h"
+#include "coff_object.h"
+#include "gpopcode.h"
+
+#define DECODE_ARG0 snprintf(buffer, sizeof_buffer, "%s", instruction->name)
+
+#define DECODE_ARG1(ARG1) snprintf(buffer, sizeof_buffer, "%s\t%#lx", \
+ instruction->name,\
+ ARG1)
+
+#define DECODE_ARG1WF(ARG1, ARG2) snprintf(buffer, sizeof_buffer, "%s\t%#lx, %s", \
+ instruction->name,\
+ ARG1, \
+ (ARG2 ? "f" : "w"))
+
+#define DECODE_ARG2(ARG1, ARG2) snprintf(buffer, sizeof_buffer, "%s\t%#lx, %#lx", \
+ instruction->name,\
+ ARG1, \
+ ARG2)
+
+#define DECODE_ARG3(ARG1, ARG2, ARG3) snprintf(buffer, sizeof_buffer, "%s\t%#lx, %#lx, %#lx", \
+ instruction->name,\
+ ARG1, \
+ ARG2, \
+ ARG3)
+
+bool gp_decode_mnemonics = false;
+bool gp_decode_extended = false;
+
+int Coff::disassemble(long int opcode, long int opcode2,
+ int org,
+ Pic::Architecture architecture,
+ char *buffer,
+ size_t sizeof_buffer)
+{
+ int i;
+ int value;
+ struct insn *instruction = NULL;
+ int num_words = 1;
+
+ switch (architecture.type()) {
+ case Pic::Architecture::P24F:
+ case Pic::Architecture::P24H:
+ case Pic::Architecture::P30F:
+ case Pic::Architecture::P33F:
+ snprintf(buffer, sizeof_buffer, "--");
+ return 0;
+ case Pic::Architecture::P10X:
+ for(i = 0; i < num_op_12c5xx; i++) {
+ if((op_12c5xx[i].mask & opcode) == op_12c5xx[i].opcode) {
+ instruction = &op_12c5xx[i];
+ break;
+ }
+ }
+ break;
+/* case PROC_CLASS_SX:
+ for(i = 0; i < num_op_sx; i++) {
+ if((op_sx[i].mask & opcode) == op_sx[i].opcode) {
+ instruction = &op_sx[i];
+ break;
+ }
+ }
+ break;
+*/
+ case Pic::Architecture::P16X:
+ for(i = 0; i < num_op_16cxx; i++) {
+ if((op_16cxx[i].mask & opcode) == op_16cxx[i].opcode) {
+ instruction = &op_16cxx[i];
+ break;
+ }
+ }
+ break;
+ case Pic::Architecture::P17C:
+ for(i = 0; i < num_op_17cxx; i++) {
+ if((op_17cxx[i].mask & opcode) == op_17cxx[i].opcode) {
+ instruction = &op_17cxx[i];
+ break;
+ }
+ }
+ break;
+ case Pic::Architecture::P18C:
+ case Pic::Architecture::P18F:
+ case Pic::Architecture::P18J:
+ if (gp_decode_mnemonics) {
+ for(i = 0; i < num_op_18cxx_sp; i++) {
+ if((op_18cxx_sp[i].mask & opcode) == op_18cxx_sp[i].opcode) {
+ instruction = &op_18cxx_sp[i];
+ break;
+ }
+ }
+ }
+ if (instruction == NULL) {
+ for(i = 0; i < num_op_18cxx; i++) {
+ if((op_18cxx[i].mask & opcode) == op_18cxx[i].opcode) {
+ instruction = &op_18cxx[i];
+ break;
+ }
+ }
+ }
+ if ((instruction == NULL) && (gp_decode_extended)) {
+ /* might be from the extended instruction set */
+ for(i = 0; i < num_op_18cxx_ext; i++) {
+ if((op_18cxx_ext[i].mask & opcode) == op_18cxx_ext[i].opcode) {
+ instruction = &op_18cxx_ext[i];
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ if (instruction == NULL) {
+ snprintf(buffer, sizeof_buffer, "dw\t%#lx ;unknown opcode", opcode);
+ return num_words;
+ }
+
+ switch (instruction->classType)
+ {
+ case INSN_CLASS_LIT3_BANK:
+ DECODE_ARG1((opcode & 0x7) << 5);
+ break;
+ case INSN_CLASS_LIT3_PAGE:
+ DECODE_ARG1((opcode & 0x7) << 9);
+ break;
+ case INSN_CLASS_LIT1:
+ DECODE_ARG1(opcode & 1);
+ break;
+ case INSN_CLASS_LIT4:
+ DECODE_ARG1(opcode & 0xf);
+ break;
+ case INSN_CLASS_LIT4S:
+ DECODE_ARG1((opcode & 0xf0) >> 4);
+ break;
+ case INSN_CLASS_LIT6:
+ DECODE_ARG1(opcode & 0x3f);
+ break;
+ case INSN_CLASS_LIT8:
+ case INSN_CLASS_LIT8C12:
+ case INSN_CLASS_LIT8C16:
+ DECODE_ARG1(opcode & 0xff);
+ break;
+ case INSN_CLASS_LIT9:
+ DECODE_ARG1(opcode & 0x1ff);
+ break;
+ case INSN_CLASS_LIT11:
+ DECODE_ARG1(opcode & 0x7ff);
+ break;
+ case INSN_CLASS_LIT13:
+ DECODE_ARG1(opcode & 0x1fff);
+ break;
+ case INSN_CLASS_LITFSR:
+ DECODE_ARG2(((opcode >> 6) & 0x3), (opcode & 0x3f));
+ break;
+ case INSN_CLASS_RBRA8:
+ value = opcode & 0xff;
+ /* twos complement number */
+ if (value & 0x80) {
+ value = -((value ^ 0xff) + 1);
+ }
+ DECODE_ARG1((unsigned long)(org + value + 1) * 2);
+ break;
+ case INSN_CLASS_RBRA11:
+ value = opcode & 0x7ff;
+ /* twos complement number */
+ if (value & 0x400) {
+ value = -((value ^ 0x7ff) + 1);
+ }
+ DECODE_ARG1((unsigned long)(org + value + 1) * 2);
+ break;
+ case INSN_CLASS_LIT20:
+ {
+ long int dest;
+
+ num_words = 2;
+ dest = (opcode2 & 0xfff) << 8;
+ dest |= opcode & 0xff;
+ DECODE_ARG1(dest * 2);
+ }
+ break;
+ case INSN_CLASS_CALL20:
+ {
+ long int dest;
+
+ num_words = 2;
+ dest = (opcode2 & 0xfff) << 8;
+ dest |= opcode & 0xff;
+ snprintf(buffer, sizeof_buffer, "%s\t%#lx, %#lx",
+ instruction->name,
+ dest * 2,
+ (opcode >> 8) & 1);
+ }
+ break;
+ case INSN_CLASS_FLIT12:
+ {
+ long int k;
+ long int file;
+
+ num_words = 2;
+ k = opcode2 & 0xff;
+ k |= ((opcode & 0xf) << 8);
+ file = (opcode >> 4) & 0x3;
+ DECODE_ARG2(file, k);
+ }
+ break;
+ case INSN_CLASS_FF:
+ {
+ long int file1;
+ long int file2;
+
+ num_words = 2;
+ file1 = opcode & 0xfff;
+ file2 = opcode2 & 0xfff;
+ DECODE_ARG2(file1, file2);
+ }
+ break;
+ case INSN_CLASS_FP:
+ DECODE_ARG2((opcode & 0xff), ((opcode >> 8) & 0x1f));
+ break;
+ case INSN_CLASS_PF:
+ DECODE_ARG2(((opcode >> 8) & 0x1f), (opcode & 0xff));
+ break;
+ case INSN_CLASS_SF:
+ {
+ long int offset;
+ long int file;
+
+ num_words = 2;
+ offset = opcode & 0x7f;
+ file = opcode2 & 0xfff;
+ DECODE_ARG2(offset, file);
+ }
+ break;
+ case INSN_CLASS_SS:
+ {
+ long int offset1;
+ long int offset2;
+
+ num_words = 2;
+ offset1 = opcode & 0x7f;
+ offset2 = opcode2 & 0x7f;
+ DECODE_ARG2(offset1, offset2);
+ }
+ break;
+ case INSN_CLASS_OPF5:
+ DECODE_ARG1(opcode & 0x1f);
+ break;
+ case INSN_CLASS_OPWF5:
+ DECODE_ARG1WF((opcode & 0x1f), ((opcode >> 5) & 1));
+ break;
+ case INSN_CLASS_B5:
+ DECODE_ARG2((opcode & 0x1f), ((opcode >> 5) & 7));
+ break;
+ case INSN_CLASS_B8:
+ DECODE_ARG2((opcode & 0xff), ((opcode >> 8) & 7));
+ break;
+ case INSN_CLASS_OPF7:
+ DECODE_ARG1(opcode & 0x7f);
+ break;
+ case INSN_CLASS_OPF8:
+ DECODE_ARG1(opcode & 0xff);
+ break;
+ case INSN_CLASS_OPWF7:
+ DECODE_ARG1WF((opcode & 0x7f), ((opcode >> 7) & 1));
+ break;
+ case INSN_CLASS_OPWF8:
+ DECODE_ARG1WF((opcode & 0xff), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_B7:
+ DECODE_ARG2((opcode & 0x7f), ((opcode >> 7) & 7));
+ break;
+ case INSN_CLASS_OPFA8:
+ DECODE_ARG2((opcode & 0xff), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_BA8:
+ DECODE_ARG3((opcode & 0xff), ((opcode >> 9) & 7), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_OPWFA8:
+ DECODE_ARG3((opcode & 0xff), ((opcode >> 9) & 1), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_IMPLICIT:
+ DECODE_ARG0;
+ break;
+ case INSN_CLASS_TBL:
+ {
+ char op[5];
+
+ switch(opcode & 0x3)
+ {
+ case 0:
+ strncpy(op, "*", sizeof(op));
+ break;
+ case 1:
+ strncpy(op, "*+", sizeof(op));
+ break;
+ case 2:
+ strncpy(op, "*-", sizeof(op));
+ break;
+ case 3:
+ strncpy(op, "+*", sizeof(op));
+ break;
+ default:
+ assert(0);
+ }
+
+ snprintf(buffer,
+ sizeof_buffer,
+ "%s\t%s",
+ instruction->name,
+ op);
+ }
+ break;
+ case INSN_CLASS_TBL2:
+ DECODE_ARG2(((opcode >> 9) & 1), (opcode & 0xff));
+ break;
+ case INSN_CLASS_TBL3:
+ DECODE_ARG3(((opcode >> 9) & 1),
+ ((opcode >> 8) & 1),
+ (opcode & 0xff));
+ break;
+ default:
+ assert(0);
+ }
+
+ return num_words;
+}