1 /* Disassemble Zylin ZPU instructions.
2    Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17 
18 #include <stdio.h>
19 #include "sysdep.h"
20 #define STATIC_TABLE
21 #define DEFINE_TABLE
22 
23 #include "opcode/zpu.h"
24 #include "zpu-opc.h"
25 #include "dis-asm.h"
26 
27 static fprintf_ftype fpr;
28 static void *stream;
29 static struct disassemble_info *local_info;
30 
31 
32 
33 
34 
35 #define GETINFO(size,type,pcrel)\
36 	case ADDR_PCREL: size = 0;type=-1;pcrel=1;break;\
37 	case ADDR_IMMEDIATE: size = 0;type=-1;pcrel=0;break;\
38 	case ADDR_IMPLIED: size = 0;type=-1;pcrel=0;break;\
39 
40 
41 
42 static void print_operand PARAMS ((int, char *, unsigned int *));
43 
44 static void
print_operand(lookup,format,args)45 print_operand (lookup, format, args)
46      int lookup;
47      char *format;
48      unsigned int *args;
49 {
50   int val;
51   int c;
52 
53   while (*format)
54     {
55       switch (c = *format++)
56 	{
57 	case '$':
58 	  val = args[(*format++) - '0'];
59 	  if (lookup)
60 	    {
61 #if 0
62 	      name = findname (val);
63 	      if (name)
64 		fpr (stream, "%s", name);
65 	      else
66 #endif
67 		local_info->print_address_func (val, local_info);
68 	    }
69 	  else
70 	    fpr (stream, "0x%x", val);
71 
72 	  break;
73 	default:
74 	  fpr (stream, "%c", c);
75 	  break;
76 	}
77     }
78 }
79 
80 int
print_insn_zpu(memaddr,info)81 print_insn_zpu (memaddr, info)
82      bfd_vma memaddr;
83      struct disassemble_info *info;
84 {
85   int status = 0;
86   unsigned char insn[4];
87   const struct zpu_opcode *op=NULL;
88   int i;
89   int args[2];
90   stream = info->stream;
91   fpr = info->fprintf_func;
92   local_info = info;
93   for (i = 0; i < 4 && status == 0; i++)
94     {
95       status = info->read_memory_func (memaddr + i, insn + i, 1, info);
96     }
97 
98 	  for (i=0; i<zpu_num_opcodes; i++)
99 	  {
100 	  	if ((zpu_opcodes[i].code==insn[0])||((zpu_opcodes[i].code&insn[0]&0x80)!=0))
101 	  	{
102 	  		op=zpu_opcodes+i;
103 	  		break;
104 	  	}
105 	  }
106 
107 	if ((insn[0]>=ZPU_storesp)&&(insn[0]<ZPU_storesp+32))
108 	{
109 		fpr (stream, "storesp %d", ((insn[0]-ZPU_storesp)^0x10)*4);
110 	} else if ((insn[0]>=ZPU_loadsp)&&(insn[0]<ZPU_loadsp+32))
111 	{
112 		fpr (stream, "loadsp %d", ((insn[0]-ZPU_loadsp)^0x10)*4);
113 	} else
114 	{
115 		switch (insn[0])
116 		{
117 			case ZPU_addsp:
118 			case ZPU_addsp+1:
119 			case ZPU_addsp+2:
120 			case ZPU_addsp+3:
121 			case ZPU_addsp+4:
122 			case ZPU_addsp+5:
123 			case ZPU_addsp+6:
124 			case ZPU_addsp+7:
125 			case ZPU_addsp+8:
126 			case ZPU_addsp+9:
127 			case ZPU_addsp+10:
128 			case ZPU_addsp+11:
129 			case ZPU_addsp+12:
130 			case ZPU_addsp+13:
131 			case ZPU_addsp+14:
132 			case ZPU_addsp+15:
133 			  fpr (stream, "addsp %d", (insn[0]-ZPU_addsp)*4);
134 			break;
135 
136 
137 
138 			default:
139 				if (op==NULL)
140 				{
141 					  fpr (stream, ".byte %d", insn[0]);
142 				} else if ((insn[0]&0x80)!=0)
143 				{
144 					int t;\
145 				  	t=(int)((signed char)((insn[0]<<1)&0xff));\
146 			  		t>>=1;\
147 
148 					fpr (stream, "im %d", t);
149 				} else
150 				{
151 				  fpr (stream, "%s", op->name);
152 
153 				  /* Prepare all the posible operand values.  */
154 				  {
155 				  	int size=1;
156 				    switch (op->amode)
157 				      {
158 					  case ADDR_IMMEDIATE:
159 					  {
160 					  	int t;
161 					  	t=(int)((signed char)((insn[0]<<1)&0xff));
162 					  	t>>=1;
163 						args[0] = t;
164 						print_operand (0, "	$0", args);
165 						size += 0;
166 					  }
167 						break;
168 					  case ADDR_IMPLIED:
169 							size += 0;
170 						break;
171 				      }
172 				  }
173 				}
174 			  break;
175 		}
176 	}
177     return 1; // size is always 1
178 }
179