* gencode.c (tab): In shad/shld definitions, negate R[m] before
[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    -d           generates a define table
27    -x           generates the simulator code switch statement
28    default      generates the opcode tables
29
30 */
31
32 #include <stdio.h>
33
34 typedef struct
35 {
36 char *defs;
37 char *refs;
38   char *name;
39   char *code;
40   char *stuff[10];
41   int index;
42 }
43
44 op;
45
46
47 op tab[] =
48 {
49
50   {"n","","add #<imm>,<REG_N>", "0111nnnni8*1....", "R[n] += SEXT(i);if (i == 0) { UNDEF(n); break; } "},
51   {"n","mn","add <REG_M>,<REG_N>", "0011nnnnmmmm1100", "R[n] += R[m];"},
52   {"n","mn","addc <REG_M>,<REG_N>", "0011nnnnmmmm1110",
53      "ult=R[n]+T;T=ult<R[n];R[n]=ult+R[m];T|=R[n]<ult;"},
54   {"n","mn","addv <REG_M>,<REG_N>", "0011nnnnmmmm1111",
55      "ult = R[n] + R[m]; T = ((~(R[n] ^ R[m]) & (ult ^ R[n])) >> 31); R[n] = ult;"},
56   {"0","","and #<imm>,R0", "11001001i8*1....", ";R0&=i;"},
57   {"n","nm","and <REG_M>,<REG_N>", "0010nnnnmmmm1001", " R[n]&=R[m];"},
58   {"","0","and.b #<imm>,@(R0,GBR)", "11001101i8*1....", ";WBAT(GBR+R0, RBAT(GBR+R0) & i);"},
59
60   {"","","bra <bdisp12>", "1010i12.........", "ult = PC; PC=PC+(i<<1)+2;SL(ult+2);"},
61   {"","","bsr <bdisp12>", "1011i12.........", "PR = PC + 4; PC=PC+(i<<1)+2;SL(PR-2);"},
62   {"","","bt <bdisp8>", "10001001i8p1....", "if(T) {PC+=(SEXT(i)<<1)+2;C+=2;}"},
63   {"","","bf <bdisp8>", "10001011i8p1....", "if(T==0) {PC+=(SEXT(i)<<1)+2;C+=2;}"},
64   {"","","bt.s <bdisp8>", "10001101i8p1....","if(T) {ult = PC; PC+=(SEXT(i)<<1)+2;C+=2;SL(ult+2);}"},
65   {"","","bf.s <bdisp8>", "10001111i8p1....","if(!T) {ult = PC; PC+=(SEXT(i)<<1)+2;C+=2;SL(ult+2);}"},
66   {"","","clrmac", "0000000000101000", "MACH = MACL = 0;"},
67   {"","","clrt", "0000000000001000", "T= 0;"},
68   {"","0","cmp/eq #<imm>,R0", "10001000i8*1....", ";T = R0 == SEXT(i);"},
69   {"","mn","cmp/eq <REG_M>,<REG_N>", "0011nnnnmmmm0000", "T=R[n]==R[m];"},
70   {"","mn","cmp/ge <REG_M>,<REG_N>", "0011nnnnmmmm0011", "T=R[n]>=R[m];"},
71   {"","mn","cmp/gt <REG_M>,<REG_N>", "0011nnnnmmmm0111", "T=R[n]>R[m];"},
72   {"","mn","cmp/hi <REG_M>,<REG_N>", "0011nnnnmmmm0110", "T=UR[n]>UR[m];"},
73   {"","mn","cmp/hs <REG_M>,<REG_N>", "0011nnnnmmmm0010", "T=UR[n]>=UR[m];"},
74   {"","n","cmp/pl <REG_N>", "0100nnnn00010101", "T = R[n]>0;"},
75   {"","n","cmp/pz <REG_N>", "0100nnnn00010001", "T = R[n]>=0;"},
76   {"","mn","cmp/str <REG_M>,<REG_N>", "0010nnnnmmmm1100",
77    "ult = R[n] ^ R[m]; T=((ult&0xff000000)==0) |((ult&0xff0000)==0) |((ult&0xff00)==0) |((ult&0xff)==0); "},
78   {"","mn","div0s <REG_M>,<REG_N>", "0010nnnnmmmm0111", "Q=(R[n]&sbit)!=0; M=(R[m]&sbit)!=0; T=M!=Q;;"},
79   {"","","div0u", "0000000000011001", "M=Q=T=0;"},
80   {"","","div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100", "T=div1(R,m,n,T);"},
81   {"n","m","exts.b <REG_M>,<REG_N>", "0110nnnnmmmm1110", "R[n] = SEXT(R[m]);"},
82   {"n","m","exts.w <REG_M>,<REG_N>", "0110nnnnmmmm1111", "R[n] = SEXTW(R[m]);"},
83   {"n","m","extu.b <REG_M>,<REG_N>", "0110nnnnmmmm1100", "R[n] = R[m] & 0xff;"},
84   {"n","m","extu.w <REG_M>,<REG_N>", "0110nnnnmmmm1101", "R[n] = R[m] & 0xffff;"},
85   {"","n","jmp @<REG_N>", "0100nnnn00101011", "ult = PC; PC=R[n]-2; SL(ult+2);"},
86   {"","n","jsr @<REG_N>", "0100nnnn00001011", "PR = PC + 4; PC=R[n]-2; if (~doprofile) gotcall(PR,PC+2);SL(PR-2);"},
87   {"","n","ldc <REG_N>,GBR", "0100nnnn00011110", "GBR=R[n];"},
88   {"","n","ldc <REG_N>,SR", "0100nnnn00001110", "SET_SR(R[n]);"},
89   {"","n","ldc <REG_N>,VBR", "0100nnnn00101110", "VBR=R[n];"},
90   {"","n","ldc.l @<REG_N>+,GBR", "0100nnnn00010111", "GBR=RLAT(R[n]);R[n]+=4;;"},
91   {"","n","ldc.l @<REG_N>+,SR", "0100nnnn00000111", "SET_SR(RLAT(R[n]));R[n]+=4;;"},
92   {"","n","ldc.l @<REG_N>+,VBR", "0100nnnn00100111", "VBR=RLAT(R[n]);R[n]+=4;;"},
93   {"","n","lds <REG_N>,MACH", "0100nnnn00001010", "MACH = R[n];"},
94   {"","n","lds <REG_N>,MACL", "0100nnnn00011010", "MACL= R[n];"},
95   {"","n","lds <REG_N>,PR", "0100nnnn00101010", "PR = R[n];"},
96   {"","n","lds.l @<REG_N>+,MACH", "0100nnnn00000110", "MACH = SEXT(RLAT(R[n]));R[n]+=4;"},
97   {"","n","lds.l @<REG_N>+,MACL", "0100nnnn00010110", "MACL = RLAT(R[n]);R[n]+=4;"},
98   {"","n","lds.l @<REG_N>+,PR", "0100nnnn00100110", "PR = RLAT(R[n]);R[n]+=4;;"},
99   {"","n","mac.w @<REG_M>+,@<REG_N>+", "0100nnnnmmmm1111", "macw(R0,memory,n,m);"},
100   {"n","","mov #<imm>,<REG_N>", "1110nnnni8*1....", "R[n] = SEXT(i);"},
101   {"n","m","mov <REG_M>,<REG_N>", "0110nnnnmmmm0011", "R[n] = R[m];"},
102   {"","mn0","mov.b <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0100", "WBAT(R[n]+R0, R[m]);"},
103   {"","nm","mov.b <REG_M>,@-<REG_N>", "0010nnnnmmmm0100", "R[n]--; WBAT(R[n],R[m]);"},
104   {"","mn","mov.b <REG_M>,@<REG_N>", "0010nnnnmmmm0000", "WBAT(R[n], R[m]);"},
105   {"0","m","mov.b @(<disp>,<REG_M>),R0", "10000100mmmmi4*1", "R0=RSBAT(i+R[m]);L(0);"},
106   {"0","","mov.b @(<disp>,GBR),R0", "11000100i8*1....", "R0=RSBAT(i+GBR);L(0);"},
107   {"n","0m","mov.b @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1100", "R[n]=RSBAT(R0+R[m]);L(n);"},
108   {"n","m","mov.b @<REG_M>+,<REG_N>", "0110nnnnmmmm0100", "R[n] = RSBAT(R[m]);L(n);R[m]++;"},
109   {"n","m","mov.b @<REG_M>,<REG_N>", "0110nnnnmmmm0000", "R[n]=RSBAT(R[m]);L(n);"},
110   {"","m0","mov.b R0,@(<disp>,<REG_M>)", "10000000mmmmi4*1", "WBAT(i+R[m],R0);"},
111   {"","0","mov.b R0,@(<disp>,GBR)", "11000000i8*1....", "WBAT(i+GBR,R0);"},
112   {"","nm","mov.l <REG_M>,@(<disp>,<REG_N>)", "0001nnnnmmmmi4*4",   "WLAT(i+R[n],R[m]);"},
113   {"","nm0","mov.l <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0110", "WLAT(R0+R[n],R[m]);"},
114   {"","nm","mov.l <REG_M>,@-<REG_N>", "0010nnnnmmmm0110", "R[n]-=4;WLAT(R[n],R[m]);"},
115   {"","nm","mov.l <REG_M>,@<REG_N>", "0010nnnnmmmm0010", "WLAT(R[n], R[m]);"},
116   {"n","m","mov.l @(<disp>,<REG_M>),<REG_N>","0101nnnnmmmmi4*4", "R[n]=RLAT(i+R[m]);L(n);"},
117   {"0","","mov.l @(<disp>,GBR),R0", "11000110i8*4....", "R0=RLAT(i+GBR);L(0);"},
118   {"n","","mov.l @(<disp>,PC),<REG_N>", "1101nnnni8p4....", "R[n]=RLAT((i+4+PC) & ~3);L(n);"},
119   {"n","m","mov.l @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1110", "R[n]=RLAT(R0+R[m]);L(n);"},
120 {"nm","m","mov.l @<REG_M>+,<REG_N>", "0110nnnnmmmm0110", "R[n]=RLAT(R[m]);R[m]+=4;L(n);"},
121   {"n","m","mov.l @<REG_M>,<REG_N>", "0110nnnnmmmm0010", "R[n]=RLAT(R[m]);L(n);"},
122   {"","0","mov.l R0,@(<disp>,GBR)", "11000010i8*4....", "WLAT(i+GBR,R0);"},
123   {"","m0n","mov.w <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0101", "WWAT(R0+R[n],R[m]);"},
124 {"n","mn","mov.w <REG_M>,@-<REG_N>", "0010nnnnmmmm0101", "R[n]-=2;WWAT(R[n],R[m]);"},
125   {"","nm","mov.w <REG_M>,@<REG_N>", "0010nnnnmmmm0001", "WWAT(R[n],R[m]);"},
126   {"0","m","mov.w @(<disp>,<REG_M>),R0", "10000101mmmmi4*2", "R0=RSWAT(i+R[m]);L(0);"},
127   {"0","","mov.w @(<disp>,GBR),R0", "11000101i8*2....", "R0=RSWAT(i+GBR);L(0);"},
128   {"n","","mov.w @(<disp>,PC),<REG_N>", "1001nnnni8p2....", "R[n]=RSWAT(PC+i+4);L(n);"},
129 {"n","m0","mov.w @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1101", "R[n]=RSWAT(R0+R[m]);L(n);"},
130 {"nm","n","mov.w @<REG_M>+,<REG_N>", "0110nnnnmmmm0101", "R[n]=RSWAT(R[m]);R[m]+=2;L(n);"},
131   {"n","m","mov.w @<REG_M>,<REG_N>", "0110nnnnmmmm0001", "R[n]=RSWAT(R[m]);L(n);"},
132   {"","0m","mov.w R0,@(<disp>,<REG_M>)", "10000001mmmmi4*2",   "WWAT(i+R[m],R0);"},
133   {"","0","mov.w R0,@(<disp>,GBR)", "11000001i8*2....", "WWAT(i+GBR,R0);"},
134   {"0","","mova @(<disp>,PC),R0", "11000111i8p4....", "R0=((i+4+PC) & ~0x3);"},
135   {"n","","movt <REG_N>", "0000nnnn00101001", "R[n]=T;"},
136   {"","mn","muls <REG_M>,<REG_N>", "0010nnnnmmmm1111","MACL=((int)(short)R[n])*((int)(short)R[m]);"},
137   {"","mn","mul.l <REG_M>,<REG_N>","0000nnnnmmmm0111","MACL=((int)R[n])*((int)R[m]);"},
138   {"","mn","mulu <REG_M>,<REG_N>", "0010nnnnmmmm1110","MACL=((unsigned int)(unsigned short)R[n])*((unsigned int)(unsigned short)R[m]);"},
139   {"n","m","neg <REG_M>,<REG_N>", "0110nnnnmmmm1011", "R[n] = - R[m];"},
140   {"n","m","negc <REG_M>,<REG_N>", "0110nnnnmmmm1010", "ult=-T;T=ult>0;R[n]=ult-R[m];T|=R[n]>ult;"},
141   {"","","nop", "0000000000001001", ""},
142   {"n","m","not <REG_M>,<REG_N>", "0110nnnnmmmm0111", "R[n]=~R[m];"},
143   {"0","","or #<imm>,R0", "11001011i8*1....", "R0|=i;"},
144   {"n","m","or <REG_M>,<REG_N>", "0010nnnnmmmm1011", "R[n]|=R[m];"},
145   {"","0","or.b #<imm>,@(R0,GBR)", "11001111i8*1....", "WBAT(R0+GBR,RBAT(R0+GBR)|i);"},
146 {"n","n","rotcl <REG_N>", "0100nnnn00100100", "ult=R[n]<0;R[n]=(R[n]<<1)|T;T=ult;"},
147   {"n","n","rotcr <REG_N>", "0100nnnn00100101", "ult=R[n]&1;R[n]=(UR[n]>>1)|(T<<31);T=ult;"},
148   {"n","n","rotl <REG_N>", "0100nnnn00000100", "T=R[n]<0;R[n]<<=1;R[n]|=T;"},
149   {"n","n","rotr <REG_N>", "0100nnnn00000101", "T=R[n]&1;R[n] = UR[n]>> 1;R[n]|=(T<<31);"},
150   {"","","rte", "0000000000101011", 
151     "{ int tmp = PC; PC=RLAT(R[15])+2;R[15]+=4;SET_SR(RLAT(R[15]) & 0x3f3);R[15]+=4;SL(tmp+2);}"},
152   {"","","rts", "0000000000001011", "ult=PC;PC=PR-2;SL(ult+2);"},
153   {"","","sett", "0000000000011000", "T=1;"},
154   {"n","mn","shad <REG_M>,<REG_N>", "0100nnnnmmmm1100",
155     "R[n] = (R[m] < 0) ? (R[n] >> ((-R[m])&0x1f)) : (R[n] << (R[m] & 0x1f));"},
156   {"n","mn","shld <REG_M>,<REG_N>", "0100nnnnmmmm1101",
157     "R[n] = (R[m] < 0) ? (UR[n] >> ((-R[m])&0x1f)): (R[n] << (R[m] & 0x1f));"},
158   {"n","n","shal <REG_N>", "0100nnnn00100000", "T=R[n]<0; R[n]<<=1;"},
159   {"n","n","shar <REG_N>", "0100nnnn00100001", "T=R[n]&1; R[n] = R[n] >> 1;"},
160   {"n","n","shll <REG_N>", "0100nnnn00000000", "T=R[n]<0; R[n]<<=1;"},
161   {"n","n","shll16 <REG_N>", "0100nnnn00101000", "R[n]<<=16;"},
162   {"n","n","shll2 <REG_N>", "0100nnnn00001000", "R[n]<<=2;"},
163   {"n","n","shll8 <REG_N>", "0100nnnn00011000", "R[n]<<=8;"},
164   {"n","n","shlr <REG_N>", "0100nnnn00000001", "T=R[n]&1;R[n]=UR[n]>>1;"},
165   {"n","n","shlr16 <REG_N>", "0100nnnn00101001", "R[n]=UR[n]>>16;"},
166   {"n","n","shlr2 <REG_N>", "0100nnnn00001001", "R[n]=UR[n]>>2;"},
167   {"n","n","shlr8 <REG_N>", "0100nnnn00011001", "R[n]=UR[n]>>8;"},
168   {"","","sleep", "0000000000011011", "trap(0xc3,R0,memory,maskl,maskw,little_endian);PC-=2;"},
169   {"n","","stc GBR,<REG_N>", "0000nnnn00010010", "R[n]=GBR;"},
170   {"n","","stc SR,<REG_N>", "0000nnnn00000010", "R[n]=GET_SR();"},
171   {"n","","stc VBR,<REG_N>", "0000nnnn00100010", "R[n]=VBR;"},
172   {"n","n","stc.l GBR,@-<REG_N>", "0100nnnn00010011", "R[n]-=4;WLAT(R[n],GBR);;"},
173   {"n","n","stc.l SR,@-<REG_N>", "0100nnnn00000011", "R[n]-=4;WLAT(R[n],GET_SR());"},
174   {"n","n","stc.l VBR,@-<REG_N>", "0100nnnn00100011", "R[n]-=4;WLAT(R[n],VBR);"},
175   {"n","","sts MACH,<REG_N>", "0000nnnn00001010", "R[n]=MACH;"},
176   {"n","","sts MACL,<REG_N>", "0000nnnn00011010", "R[n]=MACL;"},
177   {"n","","sts PR,<REG_N>", "0000nnnn00101010", "R[n]=PR;"},
178   {"n","n","sts.l MACH,@-<REG_N>", "0100nnnn00000010", "R[n]-=4;WLAT(R[n],MACH);"},
179   {"n","n","sts.l MACL,@-<REG_N>", "0100nnnn00010010", "R[n]-=4;WLAT(R[n],MACL);"},
180   {"n","n","sts.l PR,@-<REG_N>", "0100nnnn00100010", "R[n]-=4;WLAT(R[n],PR);"},
181   {"n","nm","sub <REG_M>,<REG_N>", "0011nnnnmmmm1000", "R[n]-=R[m];"},
182 {"n","nm","subc <REG_M>,<REG_N>", "0011nnnnmmmm1010", "ult=R[n]-T;T=ult>R[n];R[n]=ult-R[m];T|=R[n]>ult;"},
183   {"n","nm","subv <REG_M>,<REG_N>", "0011nnnnmmmm1011",
184      "ult = R[n] - R[m]; T = (((R[n] ^ R[m]) & (ult ^ R[n])) >> 31); R[n] = ult;"},
185   {"n","nm","swap.b <REG_M>,<REG_N>", "0110nnnnmmmm1000", "R[n]=((R[m]<<8)&0xff00)|((R[m]>>8)&0x00ff);"},
186   {"n","nm","swap.w <REG_M>,<REG_N>", "0110nnnnmmmm1001", "R[n]=((R[m]<<16)&0xffff0000)|((R[m]>>16)&0x00ffff);"},
187   {"","n","tas.b @<REG_N>", "0100nnnn00011011", "ult=RBAT(R[n]);T=ult==0;WBAT(R[n],ult|0x80);"},
188   {"0","","trapa #<imm>", "11000011i8*1....", 
189      "{ long imm = 0xff & i; if (i==0xc3) PC-=2; if (i<20||i==34||i==0xc3) trap(i,R,memory,maskl,maskw,little_endian); else { R[15]-=4; WLAT(R[15],GET_SR()); R[15]-=4;WLAT(R[15],PC+2); PC=RLAT(VBR+(imm<<2))-2;}}"},
190   {"","0","tst #<imm>,R0", "11001000i8*1....", "T=(R0&i)==0;"},
191   {"","mn","tst <REG_M>,<REG_N>", "0010nnnnmmmm1000", "T=(R[n]&R[m])==0;"},
192   {"","0","tst.b #<imm>,@(R0,GBR)", "11001100i8*1....", "T=(RBAT(GBR+R0)&i)==0;"},
193   {"","0","xor #<imm>,R0", "11001010i8*1....", "R0^=i;"},
194   {"n","mn","xor <REG_M>,<REG_N>", "0010nnnnmmmm1010", "R[n]^=R[m];"},
195   {"","0","xor.b #<imm>,@(R0,GBR)", "11001110i8*1....", "ult=RBAT(GBR+R0);ult^=i;WBAT(GBR+R0,ult);"},
196   {"n","nm","xtrct <REG_M>,<REG_N>", "0010nnnnmmmm1101", "R[n]=((R[n]>>16)&0xffff)|((R[m]<<16)&0xffff0000);"},
197   {"","nm","mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111", " MACL = R[n] * R[m];"},
198   {"n","n","dt <REG_N>", "0100nnnn00010000", "R[n]--; T=R[n] == 0;"},
199   {"","nm","dmuls.l <REG_M>,<REG_N>", "0011nnnnmmmm1101", "dmul(1,R[n],R[m]);"},
200   {"","nm","dmulu.l <REG_M>,<REG_N>", "0011nnnnmmmm0101", "dmul(0,R[n],R[m]);"},
201   {"","nm","mac.l @<REG_M>+,@<REG_N>+", "0000nnnnmmmm1111", "abort();"},
202   {"","n","braf <REG_N>", "0000nnnn00100011", "ult = PC; PC+=R[n]-2;SL(ult+2);"},
203   {"","n","bsrf <REG_N>", "0000nnnn00000011", "PR = PC + 4; PC+=R[n]-2;SL(PR-2);"},
204 #if 0
205   {"divs.l <REG_M>,<REG_N>", "0100nnnnmmmm1110", "divl(0,R[n],R[m]);"},
206   {"divu.l <REG_M>,<REG_N>", "0100nnnnmmmm1101", "divl(0,R[n],R[m]);"},
207 #endif
208
209 /* start-sanitize-sh3e */
210   {"", "", "fmov.s @<REG_M>,<FREG_N>", "1111nnnnmmmm1000", "*(int *)buf = RLAT(R[m]);F[n] = *(float *)buf;"},
211   {"", "", "fmov.s <FREG_M>,@<REG_N>", "1111nnnnmmmm1010", "*(float *)buf = F[m]; WLAT(R[n], *(int *)buf);"},
212   {"", "", "fmov.s @<REG_M>+,<FREG_N>", "1111nnnnmmmm1001", "*(int *)buf = RLAT(R[m]); F[n] = *(float *)buf; R[m] += 4;"},
213   {"", "", "fmov.s <FREG_M>,@-<REG_N>", "1111nnnnmmmm1011", "R[n] -= 4; *(float *)buf = F[m]; WLAT(R[n], *(int *)buf);"},
214   {"", "", "fmov.s @(R0,<REG_M>),<FREG_N>", "1111nnnnmmmm0110", "*(int *)buf = RLAT((R[0]+R[m]));F[n] = *(float *)buf;"},
215   {"", "", "fmov.s <FREG_M>,@(R0,<REG_N>)", "1111nnnnmmmm0111", "*(float *)buf = F[m]; WLAT((R[0]+R[n]), *(int *)buf);"},
216   {"", "", "fmov <FREG_M>,<FREG_N>", "1111nnnnmmmm1100", "F[n] = F[m];"},
217   {"", "", "fldi0 <FREG_N>", "1111nnnn10001101", "F[n] = (float)0.0;"},
218   {"", "", "fldi1 <FREG_N>", "1111nnnn10011101", "F[n] = (float)1.0;"},
219   {"", "", "fadd <FREG_M>,<FREG_N>", "1111nnnnmmmm0000","F[n] = F[n] + F[m];"},
220   {"", "", "fsub <FREG_M>,<FREG_N>", "1111nnnnmmmm0001","F[n] = F[n] - F[m];"},
221   {"", "", "fmul <FREG_M>,<FREG_N>", "1111nnnnmmmm0010","F[n] = F[n] * F[m];"},
222   {"", "", "fdiv <FREG_M>,<FREG_N>", "1111nnnnmmmm0011","F[n] = F[n] / F[m];"},
223   {"", "", "fmac <FREG_0>,<FREG_M>,<FREG_N>", "1111nnnnmmmm1110", "F[n] = F[m] * F[0] + F[n];"},
224   {"", "", "fcmp/eq <FREG_M>,<FREG_N>", "1111nnnnmmmm0100", "T = F[n] == F[m] ? 1 : 0;"},
225   {"", "", "fcmp/gt <FREG_M>,<FREG_N>", "1111nnnnmmmm0101", "T = F[n] > F[m] ? 1 : 0;"},
226   {"", "", "fneg <FREG_N>", "1111nnnn01001101", "F[n] = -F[n];"},
227   {"", "", "fabs <FREG_N>", "1111nnnn01011101", "F[n] = fabs (F[n]);"},
228   {"", "", "fsqrt <FREG_N>", "1111nnnn01101101", "F[n] = sqrt (F[n]);"},
229   {"", "", "float FPUL,<FREG_N>", "1111nnnn00101101", "F[n] = (float)FPUL;"},
230   {"", "", "ftrc <FREG_N>, FPUL", "1111nnnn00111101", "if (F[n] != F[n]) /* NaN */ FPUL = 0x80000000; else FPUL = (int)F[n];"},
231   {"", "", "ftst/nan <FREG_N>", "1111nnnn01111101", "T = isnan (F[n]);"},
232   {"", "", "fsts FPUL,<FREG_N>", "1111nnnn00001101", "*(int *)buf = FPUL; F[n] = *(float *)buf;"},
233   {"", "", "flds <FREG_N>,FPUL", "1111nnnn00011101", "*(float *)buf = F[n]; FPUL = *(int *)buf;"},
234   {"", "", "lds <REG_N>,FPUL", "0100nnnn01011010", "FPUL = R[n];"},
235   {"", "", "sts FPUL,<REG_N>", "0000nnnn01011010", "R[n] = FPUL;"},
236   {"", "", "lds <REG_N>,FPSCR", "0100nnnn01101010", "*(int *)buf = R[n]; FPSCR = *(float *)buf;"},
237   {"", "", "sts FPSCR,<REG_N>", "0000nnnn01101010", "*(float *)buf = FPSCR; R[n] = *(int *)buf;"},
238   {"","","lds.l @<REG_N>+,FPUL", "0100nnnn01010110", "FPUL = RLAT(R[n]);R[n]+=4;"},
239   {"","","lds.l @<REG_N>+,FPSCR", "0100nnnn01100110", "*(int *)buf = RLAT(R[n]); FPSCR = *(float *)buf; R[n]+=4;"},
240   {"","","sts.l FPUL,@-<REG_N>", "0100nnnn01010010", "R[n]-=4;WLAT(R[n],FPUL);"},
241   {"","","sts.l FPSCR,@-<REG_N>", "0100nnnn01100010", "R[n]-=4;*(float *)buf = FPSCR; WLAT(R[n],*(int *)buf);"},
242 /* end-sanitize-sh3e */
243
244   {0, 0}};
245
246 /* Tables of things to put into enums for sh-opc.h */
247 static char *nibble_type_list[] =
248 {
249   "HEX_0",
250   "HEX_1",
251   "HEX_2",
252   "HEX_3",
253   "HEX_4",
254   "HEX_5",
255   "HEX_6",
256   "HEX_7",
257   "HEX_8",
258   "HEX_9",
259   "HEX_A",
260   "HEX_B",
261   "HEX_C",
262   "HEX_D",
263   "HEX_E",
264   "HEX_F",
265   "REG_N",
266   "REG_M",
267   "BRANCH_12",
268   "BRANCH_8",
269   "DISP_8",
270   "DISP_4",
271   "IMM_4",
272   "IMM_4BY2",
273   "IMM_4BY4",
274   "PCRELIMM_8BY2",
275   "PCRELIMM_8BY4",
276   "IMM_8",
277   "IMM_8BY2",
278   "IMM_8BY4",
279   0
280 };
281 static
282 char *arg_type_list[] =
283 {
284   "A_END",
285   "A_BDISP12",
286   "A_BDISP8",
287   "A_DEC_M",
288   "A_DEC_N",
289   "A_DISP_GBR",
290   "A_DISP_PC",
291   "A_DISP_REG_M",
292   "A_DISP_REG_N",
293   "A_GBR",
294   "A_IMM",
295   "A_INC_M",
296   "A_INC_N",
297   "A_IND_M",
298   "A_IND_N",
299   "A_IND_R0_REG_M",
300   "A_IND_R0_REG_N",
301   "A_MACH",
302   "A_MACL",
303   "A_PR",
304   "A_R0",
305   "A_R0_GBR",
306   "A_REG_M",
307   "A_REG_N",
308   "A_SR",
309   "A_VBR",
310   0,
311 };
312
313 static void
314 make_enum_list (name, s)
315      char *name;
316      char **s;
317 {
318   int i = 1;
319   printf ("typedef enum {\n");
320   while (*s)
321     {
322       printf ("\t%s,\n", *s);
323       s++;
324       i++;
325     }
326   printf ("} %s;\n", name);
327 }
328
329 static int
330 qfunc (a, b)
331      op *a;
332      op *b;
333 {
334   char bufa[9];
335   char bufb[9];
336   memcpy (bufa, a->code, 4);
337   memcpy (bufa + 4, a->code + 12, 4);
338   bufa[8] = 0;
339
340   memcpy (bufb, b->code, 4);
341   memcpy (bufb + 4, b->code + 12, 4);
342   bufb[8] = 0;
343   return (strcmp (bufa, bufb));
344 }
345
346 static void
347 sorttab ()
348 {
349   op *p = tab;
350   int len = 0;
351
352   while (p->name)
353     {
354       p++;
355       len++;
356     }
357   qsort (tab, len, sizeof (*p), qfunc);
358 }
359
360 static void
361 printonmatch (ptr, a, rep)
362      char **ptr;
363      char *a;
364      char *rep;
365 {
366   int l = strlen (a);
367   if (strncmp (*ptr, a, l) == 0)
368     {
369       printf ("%s", rep);
370       *ptr += l;
371       if (**ptr)
372         printf (",");
373     }
374 }
375
376
377 static 
378 void
379 think (o)
380      op *o;
381 {
382   char *n;
383   char *p;
384
385   printf ("{\"");
386   n = o->name;
387   while (*n && *n != ' ')
388     {
389       printf ("%c", *n);
390       n++;
391     }
392   printf ("\",{");
393
394   p = n;
395
396   if (!*p)
397     {
398       printf ("0");
399     }
400   while (*p)
401     {
402       while (*p == ',' || *p == ' ')
403         p++;
404       printonmatch (&p, "#<imm>", "A_IMM");
405       printonmatch (&p, "R0", "A_R0");
406       printonmatch (&p, "<REG_N>", "A_REG_N");
407       printonmatch (&p, "@<REG_N>+", "A_INC_N");
408       printonmatch (&p, "@<REG_N>", "A_IND_N");
409       printonmatch (&p, "@-<REG_N>", "A_DEC_N");
410       printonmatch (&p, "<REG_M>", " A_REG_M");
411       printonmatch (&p, "@<REG_M>+", "A_INC_M");
412       printonmatch (&p, "@<REG_M>", "A_IND_M");
413       printonmatch (&p, "@-<REG_M>", "A_DEC_M");
414       printonmatch (&p, "@(<disp>,PC)", "A_DISP_PC");
415       printonmatch (&p, "@(<disp>,<REG_M>)", "A_DISP_REG_M");
416       printonmatch (&p, "@(<disp>,<REG_N>)", "A_DISP_REG_N");
417       printonmatch (&p, "@(R0,<REG_N>)", "A_IND_R0_REG_N");
418       printonmatch (&p, "@(R0,<REG_M>)", "A_IND_R0_REG_M");
419       printonmatch (&p, "@(<disp>,GBR)", "A_DISP_GBR");
420       printonmatch (&p, "@(R0,GBR)", "A_R0_GBR");
421       printonmatch (&p, "<bdisp8>", "A_BDISP8");
422       printonmatch (&p, "<bdisp12>", "A_BDISP12");
423       printonmatch (&p, "SR", "A_SR");
424       printonmatch (&p, "GBR", "A_GBR");
425       printonmatch (&p, "VBR", "A_VBR");
426       printonmatch (&p, "MACH", "A_MACH");
427       printonmatch (&p, "MACL", "A_MACL");
428       printonmatch (&p, "PR", "A_PR");
429
430     }
431   printf ("},{");
432
433   p = o->code;
434   while (*p)
435     {
436       printonmatch (&p, "0000", "HEX_0");
437       printonmatch (&p, "0001", "HEX_1");
438       printonmatch (&p, "0010", "HEX_2");
439       printonmatch (&p, "0011", "HEX_3");
440       printonmatch (&p, "0100", "HEX_4");
441       printonmatch (&p, "0101", "HEX_5");
442       printonmatch (&p, "0110", "HEX_6");
443       printonmatch (&p, "0111", "HEX_7");
444
445       printonmatch (&p, "1000", "HEX_8");
446       printonmatch (&p, "1001", "HEX_9");
447       printonmatch (&p, "1010", "HEX_A");
448       printonmatch (&p, "1011", "HEX_B");
449       printonmatch (&p, "1100", "HEX_C");
450       printonmatch (&p, "1101", "HEX_D");
451       printonmatch (&p, "1110", "HEX_E");
452       printonmatch (&p, "1111", "HEX_F");
453       printonmatch (&p, "i8*1....", "IMM_8");
454       printonmatch (&p, "i4*1", "IMM_4");
455       printonmatch (&p, "i8p4....", "PCRELIMM_8BY4");
456       printonmatch (&p, "i8p2....", "PCRELIMM_8BY2");
457       printonmatch (&p, "i8*2....", "IMM_8BY2");
458       printonmatch (&p, "i4*2", "IMM_4BY2");
459       printonmatch (&p, "i8*4....", "IMM_8BY4");
460       printonmatch (&p, "i4*4", "IMM_4BY4");
461       printonmatch (&p, "i12.........", "BRANCH_12");
462       printonmatch (&p, "i8p1....", "BRANCH_8");
463       printonmatch (&p, "nnnn", "REG_N");
464       printonmatch (&p, "mmmm", "REG_M");
465
466     }
467   printf ("}},\n");
468 }
469
470 static void
471 gengastab ()
472 {
473   op *p;
474   sorttab ();
475   for (p = tab; p->name; p++)
476     {
477       printf ("%s %-30s\n", p->code, p->name);
478     }
479
480
481 }
482
483
484 static void
485 genopc ()
486 {
487   op *p;
488   make_enum_list ("sh_nibble_type", nibble_type_list);
489   make_enum_list ("sh_arg_type", arg_type_list);
490
491   printf ("typedef struct {\n");
492   printf ("char *name;\n");
493   printf ("sh_arg_type arg[3];\n");
494   printf ("sh_nibble_type nibbles[4];\n");
495   printf ("} sh_opcode_info;\n");
496   printf ("#ifdef DEFINE_TABLE\n");
497   printf ("sh_opcode_info sh_table[]={\n");
498   for (p = tab; p->name; p++)
499     {
500       printf ("\n/* %s %-20s*/", p->code, p->name);
501       think (p);
502     }
503   printf ("0};\n");
504   printf ("#endif\n");
505 }
506
507
508
509
510
511
512 /* Convert a string of 4 binary digits into an int */
513
514 static
515 int
516 bton (s)
517      char *s;
518
519 {
520   int n = 0;
521   int v = 8;
522   while (v)
523     {
524       if (*s == '1')
525         n |= v;
526       v >>= 1;
527       s++;
528     }
529   return n;
530 }
531
532 static unsigned char table[1 << 16];
533
534 /* Take an opcode expand all varying fields in it out and fill all the
535   right entries in 'table' with the opcode index*/
536
537 static void
538 expand_opcode (shift, val, i, s)
539      int shift;
540      int val;
541      int i;
542      char *s;
543 {
544   int j;
545
546   if (*s == 0)
547     {
548       table[val] = i;
549     }
550   else
551     {
552       switch (s[0])
553         {
554
555         case '0':
556         case '1':
557           {
558
559             int n = bton (s);
560             if (n >= 0)
561               {
562                 expand_opcode (shift - 4, val | (n << shift), i, s + 4);
563               }
564             break;
565           }
566         case 'n':
567         case 'm':
568           for (j = 0; j < 16; j++)
569             {
570               expand_opcode (shift - 4, val | (j << shift), i, s + 4);
571
572             }
573           break;
574
575         default:
576           for (j = 0; j < (1 << (shift + 4)); j++)
577             {
578               table[val | j] = i;
579             }
580         }
581     }
582 }
583
584 /* Print the jump table used to index an opcode into a switch
585    statement entry. */
586
587 static void
588 dumptable ()
589 {
590   int lump = 256;
591   int online = 16;
592
593   int i = 0;
594
595   while (i < 1 << 16)
596     {
597       int j = 0;
598
599       printf ("unsigned char sh_jump_table%x[%d]={\n", i, lump);
600
601       while (j < lump)
602         {
603           int k = 0;
604           while (k < online)
605             {
606               printf ("%2d", table[i + j + k]);
607               if (j + k < lump)
608                 printf (",");
609
610               k++;
611             }
612           j += k;
613           printf ("\n");
614         }
615       i += j;
616       printf ("};\n");
617     }
618
619 }
620
621
622 static void
623 filltable ()
624 {
625   op *p;
626   int index = 1;
627
628   sorttab ();
629   for (p = tab; p->name; p++)
630     {
631       p->index = index++;
632       expand_opcode (12, 0, p->index, p->code);
633     }
634 }
635
636 static void
637 gensim ()
638 {
639   op *p;
640   int j;
641
642   printf ("{\n");
643 /* start-sanitize-sh3e */
644   printf("char buf[4];\n");
645 /* end-sanitize-sh3e */
646   printf ("switch (jump_table[iword]) {\n");
647
648   for (p = tab; p->name; p++)
649     {
650       int sextbit = -1;
651       int needm = 0;
652       int needn = 0;
653       
654       char *s = p->code;
655
656       printf ("/* %s %s */\n", p->name, p->code);
657       printf ("case %d:      \n", p->index);
658
659       printf ("{\n");
660       while (*s)
661         {
662           switch (*s)
663             {
664             case '0':
665             case '1':
666             case '.':
667               s += 4;
668               break;
669             case 'n':
670               printf ("int n =  (iword >>8) & 0xf;\n");
671               needn = 1;
672               s += 4;
673               break;
674             case 'm':
675               printf ("int m =  (iword >>4) & 0xf;\n");
676               needm = 1;
677               s += 4;
678
679               break;
680
681             case 'i':
682               printf ("int i = (iword & 0x");
683
684               switch (s[1])
685                 {
686                 case '4':
687                   printf ("f");
688                   break;
689                 case '8':
690                   printf ("ff");
691                   break;
692                 case '1':
693                   sextbit = 12;
694
695                   printf ("fff");
696                   break;
697                 }
698               printf (")");
699
700               switch (s[3])
701                 {
702                 case '1':
703                   break;
704                 case '2':
705                   printf ("<<1");
706                   break;
707                 case '4':
708                   printf ("<<2");
709                   break;
710                 }
711               printf (";\n");
712               s += 4;
713             }
714         }
715       if (sextbit > 0)
716         {
717           printf ("i = (i ^ (1<<%d))-(1<<%d);\n", sextbit - 1, sextbit - 1);
718         }
719       if (needm && needn)
720         printf("TB(m,n);");  
721       else if (needm)
722         printf("TL(m);");
723       else if (needn)
724         printf("TL(n);");
725       for (j = 0; j < 10; j++)
726         {
727           if (p->stuff[j])
728             {
729               printf ("%s\n", p->stuff[j]);
730             }
731         }
732
733       
734       {
735         /* Do the defs and refs */
736         char *r;
737         for (r = p->refs; *r; r++) {
738          if (*r == '0') printf("CREF(0);\n"); 
739          if (*r == 'n') printf("CREF(n);\n"); 
740          if (*r == 'm') printf("CREF(m);\n"); 
741          
742         }
743         for (r = p->defs; *r; r++) 
744           {
745          if (*r == '0') printf("CDEF(0);\n"); 
746          if (*r == 'n') printf("CDEF(n);\n"); 
747          if (*r == 'm') printf("CDEF(m);\n"); 
748          
749         }
750
751       }
752       printf ("break;\n");
753       printf ("}\n");
754     }
755   printf("default:\n{\nsaved_state.asregs.exception = SIGILL;\n}\n");
756   printf ("}\n}\n");
757 }
758
759
760 static void
761 gendefines ()
762 {
763   op *p;
764   filltable();
765   for (p = tab; p->name; p++)
766     {
767       char *s = p->name;
768       printf ("#define OPC_");
769       while (*s) {
770         if (isupper(*s)) 
771           *s = tolower(*s);
772         if (isalpha(*s)) printf("%c", *s);
773         if (*s == ' ') printf("_");
774         if (*s == '@') printf("ind_");
775         if (*s == ',') printf("_");
776         s++;
777       }
778       printf(" %d\n",p->index);
779     }
780 }
781
782 int
783 main (ac, av)
784      int ac;
785      char **av;
786 {
787   if (ac > 1)
788     {
789       if (strcmp (av[1], "-t") == 0)
790         {
791           gengastab ();
792         }
793       else if (strcmp (av[1], "-d") == 0)
794         {
795           gendefines ();
796         }
797       else if (strcmp (av[1], "-s") == 0)
798         {
799           filltable ();
800           dumptable ();
801
802         }
803       else if (strcmp (av[1], "-x") == 0)
804         {
805           filltable ();
806           gensim ();
807         }
808     }
809   else
810     {
811       genopc ();
812     }
813   return 0;
814 }