New stuff for SH.
[external/binutils.git] / sim / sh / gencode.c
1 /* Simulator/Opcode generator for the Hitachi Super-H architecture.
2
3    Written by Steve Chamberlain of Cygnus Support.
4    sac@cygnus.com
5
6    This file is part of SH sim
7
8
9                 THIS SOFTWARE IS NOT COPYRIGHTED
10
11    Cygnus offers the following for use in the public domain.  Cygnus
12    makes no warranty with regard to the software or it's performance
13    and the user accepts the software "AS IS" with all faults.
14
15    CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
16    THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18
19 */
20
21 /* This program generates the opcode table for the assembler and
22    the simulator code
23
24    -t           prints a pretty table for the assembler manual
25    -s           generates the simulator code jump table
26    -x           generates the simulator code switch statement
27    default      generates the opcode tables
28
29 */
30
31 typedef struct
32 {
33   char *name;
34   char *code;
35   char *stuff[10];
36   int index;
37 }
38
39 op;
40
41
42 op tab[] =
43 {
44
45   {"add #<imm>,<REG_N>", "0111nnnni8*1....", "R[n] += SEXT(i);"},
46   {"add <REG_M>,<REG_N>", "0011nnnnmmmm1100", "R[n] += R[m];"},
47   {"addc <REG_M>,<REG_N>", "0011nnnnmmmm1110", "ult = R[n]; R[n] += (R[m]+T); T = ult>R[n];"},
48   {"addv <REG_M>,<REG_N>", "0011nnnnmmmm1111",
49    "long ans;",
50    "ans = R[n] + R[m];",
51    "T = ((~R[n] & R[m] & ans) | (R[n] & R[m] & ~ans)) >>31;",
52    "R[n] = ans;"},
53
54   {"and #<imm>,R0", "11001001i8*1....", "R0&=i;"},
55   {"and <REG_M>,<REG_N>", "0010nnnnmmmm1001", "R[n]&=R[m];"},
56   {"and.b #<imm>,@(R0,GBR)", "11001101i8*1....", "WBAT(GBR+R0, RBAT(GBR+R0) & i);"},
57
58   {"bf <bdisp8>", "10001011i8p1....", "if(T==0) {PC+=(SEXT(i)<<1)+2;C+=2;}"},
59   {"bra <bdisp12>", "1010i12.........", "ult = PC; PC=PC+(i<<1)+2;SL(ult+2);"},
60   {"bsr <bdisp12>", "1011i12.........", "PR = PC; PC=PC+(i<<1)+2;SL(PR+2);"},
61   {"bt <bdisp8>", "10001001i8p1....", "if(T==1) {PC+=(SEXT(i)<<1)+2;C+=2;}"},
62   {"clrmac", "0000000000101000", "MACH = MACL = 0;"},
63   {"clrt", "0000000000001000", "T= 0;"},
64   {"cmp/eq #<imm>,R0", "10001000i8*1....", "T = R0 == SEXT(i);"},
65   {"cmp/eq <REG_M>,<REG_N>", "0011nnnnmmmm0000", "T=R[n]==R[m];"},
66   {"cmp/ge <REG_M>,<REG_N>", "0011nnnnmmmm0011", "T=R[n]>=R[m];"},
67   {"cmp/gt <REG_M>,<REG_N>", "0011nnnnmmmm0111", "T=R[n]>R[m];"},
68   {"cmp/hi <REG_M>,<REG_N>", "0011nnnnmmmm0110", "T=UR[n]>UR[m];"},
69   {"cmp/hs <REG_M>,<REG_N>", "0011nnnnmmmm0010", "T=UR[n]>=UR[m];"},
70   {"cmp/pl <REG_N>", "0100nnnn00010101", "T = R[n]>0;"},
71   {"cmp/pz <REG_N>", "0100nnnn00010001", "T = R[n]>=0;"},
72   {"cmp/str <REG_M>,<REG_N>", "0010nnnnmmmm1100", "ult = R[n] ^ R[m]; T=((ult&0xff000000)==0) |((ult&0xff0000)==0) |((ult&0xff00)==0) |((ult&0xff)==0); "},
73   {"div0s <REG_M>,<REG_N>", "0010nnnnmmmm0111", "Q=R[n]<0; M=R[m]<0; T=M!=Q;;"},
74   {"div0u", "0000000000011001", "M=Q=T=0;"},
75   {"div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100", "T=div1(R,n,m,T);"},
76   {"exts.b <REG_M>,<REG_N>", "0110nnnnmmmm1110", "R[n] = SEXT(R[m]);"},
77   {"exts.w <REG_M>,<REG_N>", "0110nnnnmmmm1111", "R[n] = SEXTW(R[m]);"},
78   {"extu.b <REG_M>,<REG_N>", "0110nnnnmmmm1100", "R[n] = R[m] & 0xff;"},
79   {"extu.w <REG_M>,<REG_N>", "0110nnnnmmmm1101", "R[n] = R[m] & 0xffff;"},
80   {"jmp @<REG_N>", "0100nnnn00101011", "ult = PC; PC=R[n]-2; SL(ult+2);"},
81   {"jsr @<REG_N>", "0100nnnn00001011", "PR = PC; PC=R[n]-2; SL(PR+2);"},
82   {"ldc <REG_N>,GBR", "0100nnnn00011110", "GBR=R[n];"},
83   {"ldc <REG_N>,SR", "0100nnnn00001110", "SET_SR(R[n]);"},
84   {"ldc <REG_N>,VBR", "0100nnnn00101110", "VBR=R[n];"},
85   {"ldc.l @<REG_N>+,GBR", "0100nnnn00010111", "GBR=RLAT(R[n]);R[n]+=4;;"},
86   {"ldc.l @<REG_N>+,SR", "0100nnnn00000111", "SET_SR(RLAT(R[n]));R[n]+=4;;"},
87   {"ldc.l @<REG_N>+,VBR", "0100nnnn00100111", "VBR=RLAT(R[n]);R[n]+=4;;"},
88   {"lds <REG_N>,MACH", "0100nnnn00001010", "MACH = SEXT(R[n]);"},
89   {"lds <REG_N>,MACL", "0100nnnn00011010", "MACL= R[n];"},
90   {"lds <REG_N>,PR", "0100nnnn00101010", "PR = R[n];"},
91   {"lds.l @<REG_N>+,MACH", "0100nnnn00000110", "MACH = SEXT(RLAT(R[n]));R[n]+=4;"},
92   {"lds.l @<REG_N>+,MACL", "0100nnnn00010110", "MACL = RLAT(R[n]);R[n]+=4;"},
93   {"lds.l @<REG_N>+,PR", "0100nnnn00100110", "PR = RLAT(R[n]);R[n]+=4;;"},
94   {"mac.w @<REG_M>+,@<REG_N>+", "0100nnnnmmmm1111", "abort();"},
95   {"mov #<imm>,<REG_N>", "1110nnnni8*1....", "R[n] = SEXT(i);"},
96   {"mov <REG_M>,<REG_N>", "0110nnnnmmmm0011", "R[n] = R[m];"},
97 {"mov.b <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0100", "WBAT(R[n]+R0, R[m]);"},
98 {"mov.b <REG_M>,@-<REG_N>", "0010nnnnmmmm0100", "R[n]--; WBAT(R[n], R[m]);"},
99   {"mov.b <REG_M>,@<REG_N>", "0010nnnnmmmm0000", "WBAT(R[n], R[m]);"},
100   {"mov.b @(<disp>,<REG_M>),R0", "10000100mmmmi4*1", "R0=RBAT(i+R[m]);"},
101   {"mov.b @(<disp>,GBR),R0", "11000100i8*1....", "R0=RBAT(i+GBR);"},
102   {"mov.b @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1100", "R[n]=RBAT(R0+R[m]);"},
103 {"mov.b @<REG_M>+,<REG_N>", "0110nnnnmmmm0100", "R[n] = RBAT(R[m]);R[m]++;"},
104   {"mov.b @<REG_M>,<REG_N>", "0110nnnnmmmm0000", "R[n]=RBAT(R[m]);"},
105   {"mov.b R0,@(<disp>,<REG_M>)", "10000000mmmmi4*1", "R0=RBAT(i+R[m]);"},
106   {"mov.b R0,@(<disp>,GBR)", "11000000i8*1....", "R0 = RBAT(i+GBR);"},
107   {"mov.l <REG_M>,@(<disp>,<REG_N>)", "0001nnnnmmmmi4*4", "WLAT(i+R[n],R[m]);"},
108   {"mov.l <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0110", "WLAT(R0+R[n],R[m]);"},
109 {"mov.l <REG_M>,@-<REG_N>", "0010nnnnmmmm0110", "R[n]-=4;WLAT(R[n],R[m]);"},
110   {"mov.l <REG_M>,@<REG_N>", "0010nnnnmmmm0010", "WLAT(R[n], R[m]);"},
111   {"mov.l @(<disp>,<REG_N>),<REG_M>", "0101nnnnmmmmi4*4", "R[m]=RLAT(i+R[n]);"},
112   {"mov.l @(<disp>,GBR),R0", "11000110i4*4", "R0=RLAT(i+GBR);"},
113   {"mov.l @(<disp>,PC),<REG_N>", "1101nnnni8p4....", "R[n]=RLAT(i+4+PC);"},
114   {"mov.l @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1110", "R[n]=RLAT(R0+R[m]);"},
115 {"mov.l @<REG_M>+,<REG_N>", "0110nnnnmmmm0110", "R[n]=RLAT(R[m]);R[m]+=4;"},
116   {"mov.l @<REG_M>,<REG_N>", "0110nnnnmmmm0010", "R[n]=RLAT(R[m]);"},
117   {"mov.l R0,@(<disp>,GBR)", "11000010i8*4....", "R0=RLAT(R0+GBR);"},
118   {"mov.w <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0101", "WWAT(R0+R[n],R[m]);"},
119 {"mov.w <REG_M>,@-<REG_N>", "0010nnnnmmmm0101", "R[n]-=2;WWAT(R[n],R[m]);"},
120   {"mov.w <REG_M>,@<REG_N>", "0010nnnnmmmm0001", "WWAT(R[n],R[m]);"},
121   {"mov.w @(<disp>,<REG_M>),R0", "10000101mmmmi4*2", "R0=RSWAT(i+R[m]);"},
122   {"mov.w @(<disp>,GBR),R0", "11000101i8*2....", "R0=RSWAT(i+GBR);"},
123   {"mov.w @(<disp>,PC),<REG_N>", "1001nnnni8p2....", "R[n]=RSWAT(PC+i+4);"},
124 {"mov.w @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1101", "R[n]=RSWAT(R0+R[m]);"},
125 {"mov.w @<REG_M>+,<REG_N>", "0110nnnnmmmm0101", "R[n]=RSWAT(R[m]);R[m]+=2;"},
126   {"mov.w @<REG_M>,<REG_N>", "0110nnnnmmmm0001", "R[n]=RSWAT(R[m]);"},
127   {"mov.w R0,@(<disp>,<REG_M>)", "10000001mmmmi4*2", "R0=RSWAT(i+R[m]);"},
128   {"mov.w R0,@(<disp>,GBR)", "11000001i8*2....", "R0=RSWAT(i+GBR);"},
129   {"mova @(<disp>,PC),R0", "11000111i8p4....", "R0=i+4+PC;"},
130   {"movt <REG_N>", "0000nnnn00101001", "R[n]=T;"},
131   {"muls <REG_M>,<REG_N>", "0010nnnnmmmm1111",
132    "MACL=((long)(short)R[n])*((long)(short)R[m]);"},
133 {"mulu <REG_M>,<REG_N>","0010nnnnmmmm1110", "MACL=((unsigned long)(unsigned short)R[n])*((unsigned long)(unsigned short)R[m]);"},  
134   {"neg <REG_M>,<REG_N>", "0110nnnnmmmm1011", "R[n] = - R[m];"},
135   {"negc <REG_M>,<REG_N>", "0110nnnnmmmm1010",  "ult=0-R[m];R[n]=ult-T;T=SBIT(R[n])!=SBIT(ult);"},
136   {"nop", "0000000000001001", ""},
137   {"not <REG_M>,<REG_N>", "0110nnnnmmmm0111", "R[n]=~R[m];"},
138   {"or #<imm>,R0", "11001011i8*1....", "R0|=i;"},
139   {"or <REG_M>,<REG_N>", "0010nnnnmmmm1011", "R[n]|=R[m];"},
140   {"or.b #<imm>,@(R0,GBR)", "11001111i8*1....", "WBAT(R0+GBR,RBAT(R0+GBR)|i);"},
141   {"rotcl <REG_N>", "0100nnnn00100100", "ult = R[n] <0;R[n] = (R[n]<<1)|T;T=ult;"},
142   {"rotcr <REG_N>", "0100nnnn00100101", "ult = R[n]&1;R[n]=(UR[n]>>1)|(T<<31);T=ult;"},
143   {"rotl <REG_N>", "0100nnnn00000100", "T=R[n]<0;R[n]<<=1;R[n]|=T;"},
144   {"rotr <REG_N>", "0100nnnn00000101", "T=R[n]&1;UR[n]>>=1;R[n]|=(T<<31);"},
145   {"rte", "0000000000101011", "abort();"},
146   {"rts", "0000000000001011", "ult=PC;PC=PR+2;SL(ult+2);"},
147   {"sett", "0000000000011000", "T=1;"},
148   {"shal <REG_N>", "0100nnnn00100000", "T=R[n]<0; R[n]<<=1;"},
149   {"shar <REG_N>", "0100nnnn00100001", "T=R[n]&1; R[n]>>=1;"},
150   {"shll <REG_N>", "0100nnnn00000000", "T=R[n]<0; R[n]<<=1;"},
151   {"shll16 <REG_N>", "0100nnnn00101000", "R[n]<<=16;"},
152   {"shll2 <REG_N>", "0100nnnn00001000", "R[n]<<=2;"},
153   {"shll8 <REG_N>", "0100nnnn00011000", "R[n]<<=8;"},
154   {"shlr <REG_N>", "0100nnnn00000001", "T=R[n]&1;R[n]=UR[n]>>1;"},
155   {"shlr16 <REG_N>", "0100nnnn00101001", "R[n]=UR[n]>>16;"},
156   {"shlr2 <REG_N>", "0100nnnn00001001", "R[n]=UR[n]>>2;"},
157   {"shlr8 <REG_N>", "0100nnnn00011001", "R[n]=UR[n]>>8;"},
158   {"sleep", "0000000000011011", "abort();"},
159   {"stc GBR,<REG_N>", "0000nnnn00010010", "R[n]=GBR;"},
160   {"stc SR,<REG_N>", "0000nnnn00000010", "R[n]=GET_SR();"},
161   {"stc VBR,<REG_N>", "0000nnnn00100010", "R[n]=VBR;"},
162   {"stc.l GBR,@-<REG_N>", "0100nnnn00010011", "R[n]-=4;WLAT(R[n],GBR);;"},
163   {"stc.l SR,@-<REG_N>", "0100nnnn00000011", "R[n]-=4;WLAT(R[n],GET_SR());"},
164   {"stc.l VBR,@-<REG_N>", "0100nnnn00100011", "R[n]-=4;WLAT(R[n],VBR);"},
165   {"sts MACH,<REG_N>", "0000nnnn00001010", "R[n]=MACH;"},
166   {"sts MACL,<REG_N>", "0000nnnn00011010", "R[n]=MACL;"},
167   {"sts PR,<REG_N>", "0000nnnn00101010", "R[n]=PR;"},
168   {"sts.l MACH,@-<REG_N>", "0100nnnn00000010", "R[n]-=4;WLAT(R[n],MACH);"},
169   {"sts.l MACL,@-<REG_N>", "0100nnnn00010010", "R[n]-=4;WLAT(R[n],MACL);"},
170   {"sts.l PR,@-<REG_N>", "0100nnnn00100010", "R[n]-=4;WLAT(R[n],PR);"},
171   {"sub <REG_M>,<REG_N>", "0011nnnnmmmm1000", "R[n]-=R[m];"},
172   {"subc <REG_M>,<REG_N>", "0011nnnnmmmm1010", "ult = R[n];R[n]-=R[m]+T;T=ult<UR[n];"},
173   {"subv <REG_M>,<REG_N>", "0011nnnnmmmm1011", "abort();"},
174   {"swap.b <REG_M>,<REG_N>", "0110nnnnmmmm1000", "R[n]=((R[m]<<8)&0xff00)|((R[m]>>8)&0x00ff);"},
175   {"swap.w <REG_M>,<REG_N>", "0110nnnnmmmm1001", "R[n]=((R[m]<<16)&0xffff0000)|((R[m]>>16)&0x00ffff);"},
176   {"tas.b @<REG_N>", "0100nnnn00011011", "ult=RBAT(R[n]);T=ult==0;WBAT(R[n],ult|0x80);"},
177   {"trapa #<imm>", "11000011i8*1....", "trap(i,R);"},
178   {"tst #<imm>,R0", "11001000i8*1....", "T=(R0&i)==0;"},
179   {"tst <REG_M>,<REG_N>", "0010nnnnmmmm1000", "T=(R[n]&R[m])==0;"},
180   {"tst.b #<imm>,@(R0,GBR)", "11001100i8*1....", "T=(RBAT(GBR+R0)&i)==0;"},
181   {"xor #<imm>,R0", "11001010i8*1....", "R0^=i;"},
182   {"xor <REG_M>,<REG_N>", "0010nnnnmmmm1010", "R[n]^=R[m];"},
183   {"xor.b #<imm>,@(R0,GBR)", "11001110i8*1....", "ult=RBAT(GBR+R0);ult^=i;WBAT(GBR+R0,ult);"},
184   {"xtrct <REG_M>,<REG_N>", "0010nnnnmmmm1101", "R[n]=((R[n]>>16)&0xffff)|((R[m]<<16)&0xffff0000);"},
185
186 #if 0
187 {"mul.l <REG_M>,<REG_N>","0000nnnnmmmm0111","/* mull */"},
188 {"dmuls.l <REG_M>,<REG_N>","0011nnnnmmmm1101","/* dmuls.l */"},
189 {"dmulu.l <REG_M>,<REG_N>","0011nnnnmmmm0101",""},
190 {"mac.l @<REG_M>+,@<REG_N>+","0000nnnnmmmm1111",""},
191 {"bt/s <bdisp8>","10001101i8p1....",""},
192 {"bf/s <bdisp8>","10001111i8p1....",""},
193 {"dt <REG_N>","0100nnnn00010000",""},
194 {"braf @<REG_N>","0000nnnn00100011",""},
195 {"bsrf @<REG_N>","0000nnnn00000011",""},
196 {"mulu <REG_M>,<REG_N>","0010nnnnmmmm1110",""},
197 {"muls <REG_M>,<REG_N>","0010nnnnmmmm1111",""},     
198 #endif
199
200   {0, 0}};
201
202 /* Tables of things to put into enums for sh-opc.h */
203 static char *nibble_type_list[] =
204 {
205   "HEX_0",
206   "HEX_1",
207   "HEX_2",
208   "HEX_3",
209   "HEX_4",
210   "HEX_5",
211   "HEX_6",
212   "HEX_7",
213   "HEX_8",
214   "HEX_9",
215   "HEX_A",
216   "HEX_B",
217   "HEX_C",
218   "HEX_D",
219   "HEX_E",
220   "HEX_F",
221   "REG_N",
222   "REG_M",
223   "BRANCH_12",
224   "BRANCH_8",
225   "DISP_8",
226   "DISP_4",
227   "IMM_4",
228   "IMM_4BY2",
229   "IMM_4BY4",
230   "PCRELIMM_8BY2",
231   "PCRELIMM_8BY4",
232   "IMM_8",
233   "IMM_8BY2",
234   "IMM_8BY4",
235   0
236 };
237 static
238 char *arg_type_list[] =
239 {
240   "A_END",
241   "A_BDISP12",
242   "A_BDISP8",
243   "A_DEC_M",
244   "A_DEC_N",
245   "A_DISP_GBR",
246   "A_DISP_PC",
247   "A_DISP_REG_M",
248   "A_DISP_REG_N",
249   "A_GBR",
250   "A_IMM",
251   "A_INC_M",
252   "A_INC_N",
253   "A_IND_M",
254   "A_IND_N",
255   "A_IND_R0_REG_M",
256   "A_IND_R0_REG_N",
257   "A_MACH",
258   "A_MACL",
259   "A_PR",
260   "A_R0",
261   "A_R0_GBR",
262   "A_REG_M",
263   "A_REG_N",
264   "A_SR",
265   "A_VBR",
266   0,
267 };
268
269 static void
270 make_enum_list (name, s)
271      char *name;
272      char **s;
273 {
274   int i = 1;
275   printf ("typedef enum {\n");
276   while (*s)
277     {
278       printf ("\t%s,\n", *s, i);
279       s++;
280       i++;
281     }
282   printf ("} %s;\n", name);
283 }
284
285 static void
286 gengastab ()
287 {
288   op *p;
289   sorttab ();
290   for (p = tab; p->name; p++)
291     {
292       printf ("%s %-30s\n", p->code, p->name);
293     }
294
295
296 }
297
298
299 static void 
300 genopc ()
301 {
302   op *p;
303   make_enum_list ("sh_nibble_type", nibble_type_list);
304   make_enum_list ("sh_arg_type", arg_type_list);
305
306   printf ("typedef struct {\n");
307   printf ("char *name;\n");
308   printf ("sh_arg_type arg[3];\n");
309   printf ("sh_nibble_type nibbles[4];\n");
310   printf ("} sh_opcode_info;\n");
311   printf ("#ifdef DEFINE_TABLE\n");
312   printf ("sh_opcode_info sh_table[]={\n");
313   for (p = tab; p->name; p++)
314     {
315       printf ("\n\/\* %s %-20s*/", p->code, p->name);
316       think (p);
317     }
318   printf ("0};\n");
319   printf ("#endif\n");
320 }
321
322
323 m (ptr, a, rep)
324      char **ptr;
325      char *a;
326      char *rep;
327 {
328   int l = strlen (a);
329   if (strncmp (*ptr, a, l) == 0)
330     {
331       printf ("%s", rep);
332       *ptr += l;
333       if (**ptr)
334         printf (",");
335     }
336 }
337
338 think (o)
339      op *o;
340 {
341   int t;
342   char *n;
343   char *p;
344
345   printf ("{\"");
346   n = o->name;
347   while (*n && *n != ' ')
348     {
349       printf ("%c", *n);
350       n++;
351     }
352   printf ("\",{");
353
354   p = n;
355
356   if (!*p)
357     {
358       printf ("0");
359     }
360   while (*p)
361     {
362       while (*p == ',' || *p == ' ')
363         p++;
364       m (&p, "#<imm>", "A_IMM");
365       m (&p, "R0", "A_R0");
366       m (&p, "<REG_N>", "A_REG_N");
367       m (&p, "@<REG_N>+", "A_INC_N");
368       m (&p, "@<REG_N>", "A_IND_N");
369       m (&p, "@-<REG_N>", "A_DEC_N");
370       m (&p, "<REG_M>", " A_REG_M");
371       m (&p, "@<REG_M>+", "A_INC_M");
372       m (&p, "@<REG_M>", "A_IND_M");
373       m (&p, "@-<REG_M>", "A_DEC_M");
374       m (&p, "@(<disp>,PC)", "A_DISP_PC");
375       m (&p, "@(<disp>,<REG_M>)", "A_DISP_REG_M");
376       m (&p, "@(<disp>,<REG_N>)", "A_DISP_REG_N");
377       m (&p, "@(R0,<REG_N>)", "A_IND_R0_REG_N");
378       m (&p, "@(R0,<REG_M>)", "A_IND_R0_REG_M");
379       m (&p, "@(<disp>,GBR)", "A_DISP_GBR");
380       m (&p, "@(R0,GBR)", "A_R0_GBR");
381       m (&p, "<bdisp8>", "A_BDISP8");
382       m (&p, "<bdisp12>", "A_BDISP12");
383       m (&p, "SR", "A_SR");
384       m (&p, "GBR", "A_GBR");
385       m (&p, "VBR", "A_VBR");
386       m (&p, "MACH", "A_MACH");
387       m (&p, "MACL", "A_MACL");
388       m (&p, "PR", "A_PR");
389
390     }
391   printf ("},{");
392
393   p = o->code;
394   while (*p)
395     {
396       m (&p, "0000", "HEX_0");
397       m (&p, "0001", "HEX_1");
398       m (&p, "0010", "HEX_2");
399       m (&p, "0011", "HEX_3");
400       m (&p, "0100", "HEX_4");
401       m (&p, "0101", "HEX_5");
402       m (&p, "0110", "HEX_6");
403       m (&p, "0111", "HEX_7");
404
405       m (&p, "1000", "HEX_8");
406       m (&p, "1001", "HEX_9");
407       m (&p, "1010", "HEX_A");
408       m (&p, "1011", "HEX_B");
409       m (&p, "1100", "HEX_C");
410       m (&p, "1101", "HEX_D");
411       m (&p, "1110", "HEX_E");
412       m (&p, "1111", "HEX_F");
413       m (&p, "i8*1....", "IMM_8");
414       m (&p, "i4*1", "IMM_4");
415       m (&p, "i8p4....", "PCRELIMM_8BY4");
416       m (&p, "i8p2....", "PCRELIMM_8BY2");
417       m (&p, "i8*2....", "IMM_8BY2");
418       m (&p, "i4*2", "IMM_4BY2");
419       m (&p, "i8*4....", "IMM_8BY4");
420       m (&p, "i4*4", "IMM_4BY4");
421       m (&p, "i12.........", "BRANCH_12");
422       m (&p, "i8p1....", "BRANCH_8");
423       m (&p, "nnnn", "REG_N");
424       m (&p, "mmmm", "REG_M");
425
426     }
427   printf ("}},\n");
428 }
429
430 qfunc (a, b)
431      op *a;
432      op *b;
433 {
434   char bufa[9];
435   char bufb[9];
436   memcpy (bufa, a->code, 4);
437   memcpy (bufa + 4, a->code + 12, 4);
438   bufa[8] = 0;
439
440   memcpy (bufb, b->code, 4);
441   memcpy (bufb + 4, b->code + 12, 4);
442   bufb[8] = 0;
443   return (strcmp (bufa, bufb));
444 }
445
446
447 sorttab ()
448 {
449   op *p = tab;
450
451   int len = 0;
452
453   while (p->name)
454     {
455       p++;
456       len++;
457     }
458
459   qsort (tab, len, sizeof (*p), qfunc);
460
461 }
462
463 /* Convert a string of 4 binary digits into an int */
464
465 static
466 int
467 bton (s)
468      char *s;
469
470 {
471   int n = 0;
472   int v = 8;
473   while (v)
474     {
475       if (*s == '1')
476         n |= v;
477       v >>= 1;
478       s++;
479     }
480   return n;
481 }
482
483 static char table[1 << 16];
484
485 /* Take an opcode expand all varying fields in it out and fill all the 
486   right entries in 'table' with the opcode index*/
487     
488 expand_opcode (shift, val, i, s)
489      char *s;
490 {
491   int j;
492
493   if (*s == 0)
494     {
495       table[val] = i;
496     }
497   else
498     {
499       switch (s[0])
500         {
501
502         case '0':
503         case '1':
504           {
505
506             int n = bton (s);
507             if (n >= 0)
508               {
509                 expand_opcode (shift - 4, val | (n << shift), i, s + 4);
510               }
511             break;
512           }
513         case 'n':
514         case 'm':
515           for (j = 0; j < 16; j++)
516             {
517               expand_opcode (shift - 4, val | (j << shift), i, s + 4);
518
519             }
520           break;
521
522         default:
523           for (j = 0; j < (1 << (shift + 4)); j++)
524             {
525               table[val | j] = i;
526             }
527         }
528     }
529 }
530
531 /* Print the jump table used to index an opcode into a switch
532   statement entry */
533 static void
534
535 dumptable ()
536 {
537   int lump = 256;
538   int online = 16;
539
540   int i = 0;
541
542   while (i < 1 << 16)
543     {
544       int j = 0;
545       int nc = 0;
546
547       printf ("unsigned char sh_jump_table%x[%d]={\n", i, lump);
548
549       while (j < lump)
550         {
551           int k = 0;
552           while (k < online)
553             {
554               printf ("%2d", table[i + j + k]);
555               if (j + k < lump)
556                 printf (",");
557
558               k++;
559             }
560           j += k;
561           printf ("\n");
562         }
563       i += j;
564       printf ("};\n");
565     }
566
567 }
568
569
570 static void
571 filltable ()
572 {
573   op *p;
574   int index = 1;
575
576   sorttab ();
577   for (p = tab; p->name; p++)
578     {
579       p->index = index++;
580       expand_opcode (12, 0, p->index, p->code);
581     }
582 }
583
584 static void 
585 gensim ()
586 {
587   op *p;
588   int j;
589
590   printf ("{\n");
591   printf ("switch (jump_table[iword]) {\n");
592
593   for (p = tab; p->name; p++)
594     {
595       int sextbit = -1;
596    
597       char *s = p->code;
598
599       printf ("\/\* %s %s *\/\n", p->name, p->code);
600       printf ("case %d:      \n", p->index);
601
602       printf ("{\n");
603       while (*s)
604         {
605           switch (*s)
606             {
607             case '0':
608             case '1':
609             case '.':
610               s += 4;
611               break;
612             case 'n':
613               printf ("int n =  (iword >>8) & 0xf;\n");
614               s += 4;
615               break;
616             case 'm':
617               printf ("int m =  (iword >>4) & 0xf;\n");
618               s += 4;
619
620               break;
621
622             case 'i':
623               printf ("int i = (iword & 0x");
624
625               switch (s[1])
626                 {
627                 case '4':
628                   printf ("f");
629                   break;
630                 case '8':
631                   printf ("ff");
632                   break;
633                 case '1':
634                   sextbit = 12;
635                   
636                   printf ("fff");
637                   break;
638                 }
639               printf (")");
640
641               switch (s[3])
642                 {
643                 case '1':
644                   break;
645                 case '2':
646                   printf ("<<1");
647                   break;
648                 case '4':
649                   printf ("<<2");
650                   break;
651                 }
652               printf (";\n");
653               s += 4;
654             }
655         }
656       if (sextbit>0) 
657         {
658           printf("i = (i ^ (1<<%d))-(1<<%d);\n",sextbit-1,sextbit-1);
659         }
660       
661       for (j = 0; j < 10; j++)
662         {
663           if (p->stuff[j])
664             {
665               printf ("%s\n", p->stuff[j]);
666             }
667         }
668       printf ("break;\n", p->stuff);
669       printf ("}\n");
670     }
671   printf ("}\n}\n");
672 }
673
674
675 int
676 main (ac, av)
677      char **av;
678
679 {
680   if (ac > 1)
681     {
682       if (strcmp (av[1], "-t") == 0)
683         {
684           gengastab ();
685         }
686       else if (strcmp (av[1], "-s") == 0)
687         {
688           filltable ();
689           dumptable ();
690
691         }
692       else if (strcmp (av[1], "-x") == 0)
693         {
694           filltable ();
695           gensim ();
696         }
697     }
698   else
699     {
700       genopc ();
701     }
702   return 0;
703 }