[linux-unicore] [RFC binutils/opcodes 3/3] Functions and Data to specified UniCore32's instructions.

  • From: LIU Zhiyou <liuzhiyou.cs@xxxxxxxxx>
  • To: linux-unicore@xxxxxxxxxxxxx
  • Date: Tue, 25 Dec 2012 23:56:02 +0800

Since struct inst only have `raw' field, it does not need
a specified initialize function. But we have lots types of
arguments. They are initializing in two ways, 1) content of
the argument is held in a single field and 2) content is
separated into two fields. This two ways can be initialize
by init_singlefield and init_combinefield respectively.
We also want to make the knowledge of how to disassemble
every type of argument as data(function), so we have
`print_arg_r', ``print_arg_rbase', etc.

P.S. Not all instructions are descripted now.

Signed-off-by: LIU Zhiyou <liuzhiyou.cs@xxxxxxxxx>
---
 opcodes/unicore32-opc.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 236 insertions(+)
 create mode 100644 opcodes/unicore32-opc.c

diff --git a/opcodes/unicore32-opc.c b/opcodes/unicore32-opc.c
new file mode 100644
index 0000000..7caca1f
--- /dev/null
+++ b/opcodes/unicore32-opc.c
@@ -0,0 +1,236 @@
+/* unicore32-opc.c -- Table of opcodes for the UniCore32 processor.
+   Copyright 2007, 2008, 2010  Free Software Foundation, Inc.
+   Contributed by LIU Zhiyou (liuzhiyou.cs@xxxxxxxxx)
+
+   This file is part of the GNU opcodes library.
+
+   This library 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 3, or (at your option)
+   any later version.
+
+   It 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "opcode/unicore32.h"
+
+short inst_width[] = {
+#define InstF(name, width, offset)    width,
+
+InstField_DEF
+
+#undef InstF
+};
+
+short inst_offset[] = {
+#define InstF(name, width, offset)    offset,
+
+InstField_DEF
+
+#undef InstF
+}
+
+static unsigned long get_inst_field(inst const *ainst, inst_fields field) {
+    return (ainst->raw >> inst_offset[field]) &
+        ((1UL << inst_width[field]) - 1UL);
+}
+
+static long u2s(unsigned long us, short width) {
+    return us | (-1L ^ ((1L << width) -1 ));
+}
+
+static void init_singlefield(inst *ainst, argument* arg) {
+    arg.ucontent.raw = get_inst_field(ainst, arg.type.field1);
+    arg.scontent = u2s(arg.ucontent.raw, inst_width[arg.type.field1]);
+    return ;
+}
+
+static void init_combinefield(inst *ainst, argument* arg) {
+    unsigned long field_content = get_isnt_field(ainst, arg.type.field1);
+    field_content <<= inst_width[arg.type.field2];
+    field_content |= get_inst_field(ainst, arg.typ.field2);
+    ucontent.raw = field_content;
+    arg.scontent = u2s(arg.ucontent.raw,
+                       inst_width[arg.type.field1]+
+                       inst_width[arg.type.field2]);
+    return ;
+}
+
+/***
+ * print argument as regard register
+ * TODO: Make it better
+ ***/
+static void print_arg_r(isnt *ainst, argument *arg, struct disassemble_info 
*info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    func(stream, "r%d", (int)arg.ucontent.areg);
+}
+
+
+
+/***
+ * print argument as shift imm5.
+ * in type: D_Imm_Shift, M_Imm_Shift
+ ***/
+static void print_arg_shiftimm(isnt *ainst, argument *arg, struct 
disassemble_info *info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    char const * shift_map[] = {"<<", ">>", "|>", "<>"};
+    func(stream, "%s #%lu", shift_map[shift], arg.ucontent.uimm);
+}
+
+/***
+ * shift with a register
+ * in type: D_Reg_Shift, M_Reg_Shift
+ ***/
+static void print_arg_shiftr(isnt *ainst, argument *arg, struct 
disassemble_info *info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    char const * shift_map[] = {"<<", ">>", "|>", "<>"};
+    unsigned long shift = get_inst_field(ainst, InstField_Shift);
+    func(stream, "%s r%d", shift_map[shift], arg.ucontent.areg);
+}
+
+/***
+ * imm in inst with field `rotate', signed
+ * in type: D_Immediate, MvToStFlag
+ ***/
+static void print_arg_rotateimm(isnt *ainst, argument *arg, struct 
disassemble_info *info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    /* TODO: stub */
+}
+
+/***
+ * unsigned imm
+ ***/
+static void print_arg_uimm(isnt *ainst, argument *arg, struct disassemble_info 
*info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    unsigned long uimm = arg.ucontent.uimm;
+    func(stream, "#%lu", uimm);
+}
+
+/***
+ * signed imm, for example, imm14 on L/S instructions
+ ***/
+static void print_arg_simm(isnt *ainst, argument *arg, struct disassemble_info 
*info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    func(stream, "#%ld", arg.scontent);
+}
+
+
+/***
+ * register as address base
+ * in type: L/S instructions
+ ***/
+static void print_arg_rbase(isnt *ainst, argument *arg, struct 
disassemble_info *info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    reg rbase = arg.ucontent.areg;
+    char *fmt[] = {"[r%d]%c, [r%d%c]"};
+    char op[] = {'-', '+'};
+    func(stream, fmt[get_inst_field(ainst, InstField_P)],
+         rbase, op[get_inst_field(ainst, InstField_U)]);
+}
+
+/***
+ * Register List, in L/S multipy
+ */
+static void print_arg_lsmulti() (isnt *ainst, argument *arg, struct 
disassemble_info *info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    unsigned long reg_bitmap = arg.ucontent.raw;
+    int base = get_inst_field(InstField_H)? 16 : 0;
+    int first_reg = 1;
+    for (int i = 0; i < 16; i++) {
+        if (reg_bitmap & (1 << i)) {
+            if (first_reg) 
+                first_reg = 0;
+            else
+                func(stream, ' ');
+            func(stream, 'r%d', base+i);
+        }
+    }
+}
+
+argument_type noarg = {
+    .init = NULL;
+    .print_arg = NULL;
+};
+
+void print_inst_arith(inst *ainst, struct disassemble_info *info) {
+    PTR stream = info->stream;
+    fprintf_ftype func = info->fprintf_func;
+    func(stream, "%s", ainst->prefix);
+    if (get_inst_field(ainst, InstField_S))
+        func(stream, ".a");
+}
+
+#define SingleField(field) init_singlefield, field, 0
+#define ARG_T(INIT, PRINT) {INIT, PRINT}
+#define ARG_SingleField(field, PRINT) SingleField(field), PRINT
+inst_type inst_types[] = {
+// for D_Imm_Shift and D_Reg_Shift    
+#define ARITH_INS(prefix, opcodes)
+    { prefix,                                           \
+      /**/B32(11111111, 00000000, 00000001, 00100000),  \
+      B32(000##opcodes, 00000000, 00000000, 00000000),  \
+      print_inst_arith,                                 \
+      {ARG_SingleField(InstField_Rd, print_arg_r),      \
+       ARG_SingleField(InstField_Rn, print_arg_r),      \
+       ARG_SingleField(InstField_Rm, print_arg_r),              \
+       ARG_SingleField(InstField_ShiftImm, print_arg_shiftimm)\
+      }\
+    },\
+    { prefix,\
+      /**/B32(11111111, 00000000, 00000001, 00100000),\
+      B32(000##opcodes, 00000000, 00000001, 00000000),\
+      print_inst_arith\
+      {ARG_SingleField(InstField_Rd, print_arg_r),\
+       ARG_SingleField(InstField_Rn, print_arg_r),\
+       ARG_SingleField(InstField_Rm, print_arg_r),\
+       ARG_SingleField(InstField_Rs, print_arg_shiftr)\
+      }\
+    }
+    
+    ARITH_INS("and", 00000),
+    ARITH_INS("xor", 00001),
+    ARITH_INS("sub", 00010),
+    ARITH_INS("rsub", 00011),
+    ARITH_INS("add", 00100),
+    ARITH_INS("addc", 00101),
+    ARITH_INS("subc", 00110),
+    ARITH_INS("rsubc", 00111),
+    ARITH_INS("undefined", 01000),
+    ARITH_INS("undefined", 01001),
+    ARITH_INS("undefined", 01010),
+    ARITH_INS("undefined", 01011),
+    ARITH_INS("or", 01100),
+    ARITH_INS("mov", 01101),
+    ARITH_INS("andn", 01110),
+    ARITH_INS("not", 01111),
+    ARITH_INS("and", 10000),
+    ARITH_INS("xor", 10001),
+    ARITH_INS("sub", 10010),
+    ARITH_INS("rsub", 10011),
+    ARITH_INS("add", 10100),
+    ARITH_INS("addc", 10101),
+    ARITH_INS("subc", 10110),
+    ARITH_INS("rsubc", 10111),
+    ARITH_INS("undefined", 11000),
+    ARITH_INS("undefined", 11001),
+    ARITH_INS("undefined", 11010),
+    ARITH_INS("undefined", 11011),
+    ARITH_INS("or", 11100),
+    ARITH_INS("mov", 11101),
+    ARITH_INS("andn", 11110),
+    ARITH_INS("not", 11111),
+};
-- 
1.8.0.2


Other related posts:

  • » [linux-unicore] [RFC binutils/opcodes 3/3] Functions and Data to specified UniCore32's instructions. - LIU Zhiyou