1 /* pyramid.opcode.h -- gdb initial attempt.
2 
3    Copyright (C) 2001-2024 Free Software Foundation, Inc.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3, or (at your option)
8    any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street - Fifth Floor,
18    Boston, MA 02110-1301, USA.  */
19 
20 /* pyramid opcode table: wot to do with this
21    particular opcode */
22 
23 struct pyr_datum
24 {
25   char              nargs;
26   char *            args;     /* how to compile said opcode */
27   unsigned long     mask;     /* Bit vector: which operand modes are valid
28                                            for this opcode */
29   unsigned char     code;     /* op-code (always 6(?) bits */
30 };
31 
32 typedef struct pyr_insn_format
33 {
34     unsigned int mode :4;
35     unsigned int operator :8;
36     unsigned int index_scale :2;
37     unsigned int index_reg :6;
38     unsigned int operand_1 :6;
39     unsigned int operand_2:6;
40 } pyr_insn_format;
41 
42 
43 /* We store four bytes of opcode for all opcodes.
44    Pyramid is sufficiently RISCy that:
45       - insns are always an integral number of words;
46       - the length of any insn can be told from the first word of
47         the insn. (ie, if there are zero, one, or two words of
48           immediate operand/offset).
49 
50 
51    The args component is a string containing two characters for each
52    operand of the instruction.  The first specifies the kind of operand;
53    the second, the place it is stored. */
54 
55 /* Kinds of operands:
56    mask    assembler syntax   description
57    0x0001:  movw Rn,Rn                  register to register
58    0x0002:  movw K,Rn                   quick immediate to register
59    0x0004:  movw I,Rn                   long immediate to register
60    0x0008:  movw (Rn),Rn      register indirect to register
61               movw (Rn)[x],Rn register indirect to register
62    0x0010:  movw I(Rn),Rn     offset register indirect to register
63               movw I(Rn)[x],Rn          offset register indirect, indexed, to register
64 
65    0x0020:  movw Rn,(Rn)      register to register indirect
66    0x0040:  movw K,(Rn)                 quick immediate to register indirect
67    0x0080:  movw I,(Rn)                 long immediate to register indirect
68    0x0100:  movw (Rn),(Rn)    register indirect to-register indirect
69    0x0100:  movw (Rn),(Rn)    register indirect to-register indirect
70    0x0200:  movw I(Rn),(Rn)   register indirect+offset to register indirect
71    0x0200:  movw I(Rn),(Rn)   register indirect+offset to register indirect
72 
73    0x0400:  movw Rn,I(Rn)     register to register indirect+offset
74    0x0800:  movw K,I(Rn)      quick immediate to register indirect+offset
75    0x1000:  movw I,I(Rn)      long immediate to register indirect+offset
76    0x1000:  movw (Rn),I(Rn)   register indirect to-register indirect+offset
77    0x1000:  movw I(Rn),I(Rn)  register indirect+offset to register indirect
78                                                   +offset
79    0x0000:  (irregular)                 ???
80 
81 
82    Each insn has a four-bit field encoding the type(s) of its operands.
83 */
84 
85 /* Some common combinations
86    */
87 
88 /* the first 5,(0x1|0x2|0x4|0x8|0x10) ie (1|2|4|8|16), ie ( 32 -1)*/
89 #define GEN_TO_REG (31)
90 
91 #define   UNKNOWN ((unsigned long)-1)
92 #define ANY (GEN_TO_REG | (GEN_TO_REG << 5) | (GEN_TO_REG << 15))
93 
94 #define CONVERT (1|8|0x10|0x20|0x200)
95 
96 #define K_TO_REG (2)
97 #define I_TO_REG (4)
98 #define NOTK_TO_REG (GEN_TO_REG & ~K_TO_REG)
99 #define NOTI_TO_REG (GEN_TO_REG & ~I_TO_REG)
100 
101 /* The assembler requires that this array be sorted as follows:
102    all instances of the same mnemonic must be consecutive.
103    All instances of the same mnemonic with the same number of operands
104    must be consecutive.
105  */
106 
107 struct pyr_opcode             /* pyr opcode text */
108 {
109   char *            name;     /* opcode name: lowercase string  [key]  */
110   struct pyr_datum  datum;    /* rest of opcode table          [datum] */
111 };
112 
113 #define pyr_how args
114 #define pyr_nargs nargs
115 #define pyr_mask mask
116 #define pyr_name name
117 
118 struct pyr_opcode pyr_opcodes[] =
119 {
120   {"movb",          { 2, "", UNKNOWN,             0x11}, },
121   {"movh",          { 2, "", UNKNOWN,             0x12} },
122   {"movw",          { 2, "", ANY,                           0x10} },
123   {"movl",          { 2, "", ANY,                           0x13} },
124   {"mnegw",         { 2, "", (0x1|0x8|0x10),      0x14} },
125   {"mnegf",         { 2, "", 0x1,                           0x15} },
126   {"mnegd",         { 2, "", 0x1,                           0x16} },
127   {"mcomw",         { 2, "", (0x1|0x8|0x10),      0x17} },
128   {"mabsw",         { 2, "", (0x1|0x8|0x10),      0x18} },
129   {"mabsf",         { 2, "", 0x1,                           0x19} },
130   {"mabsd",         { 2, "", 0x1,                           0x1a} },
131   {"mtstw",         { 2, "", (0x1|0x8|0x10),      0x1c} },
132   {"mtstf",         { 2, "", 0x1,                           0x1d} },
133   {"mtstd",         { 2, "", 0x1,                           0x1e} },
134   {"mova",          { 2, "", 0x8|0x10,            0x1f} },
135   {"movzbw",        { 2, "", (0x1|0x8|0x10),      0x20} },
136   {"movzhw",        { 2, "", (0x1|0x8|0x10),      0x21} },
137                                         /* 2 insns out of order here */
138   {"movbl",         { 2, "", 1,                             0x4f} },
139   {"filbl",         { 2, "", 1,                             0x4e} },
140 
141   {"cvtbw",         { 2, "", CONVERT,             0x22} },
142   {"cvthw",         { 2, "", CONVERT,             0x23} },
143   {"cvtwb",         { 2, "", CONVERT,             0x24} },
144   {"cvtwh",         { 2, "", CONVERT,             0x25} },
145   {"cvtwf",         { 2, "", CONVERT,             0x26} },
146   {"cvtwd",         { 2, "", CONVERT,             0x27} },
147   {"cvtfw",         { 2, "", CONVERT,             0x28} },
148   {"cvtfd",         { 2, "", CONVERT,             0x29} },
149   {"cvtdw",         { 2, "", CONVERT,             0x2a} },
150   {"cvtdf",         { 2, "", CONVERT,             0x2b} },
151 
152   {"addw",          { 2, "", GEN_TO_REG,                    0x40} },
153   {"addwc",         { 2, "", GEN_TO_REG,                    0x41} },
154   {"subw",          { 2, "", GEN_TO_REG,                    0x42} },
155   {"subwb",         { 2, "", GEN_TO_REG,                    0x43} },
156   {"rsubw",         { 2, "", GEN_TO_REG,                    0x44} },
157   {"mulw",          { 2, "", GEN_TO_REG,                    0x45} },
158   {"emul",          { 2, "", GEN_TO_REG,                    0x47} },
159   {"umulw",         { 2, "", GEN_TO_REG,                    0x46} },
160   {"divw",          { 2, "", GEN_TO_REG,                    0x48} },
161   {"ediv",          { 2, "", GEN_TO_REG,                    0x4a} },
162   {"rdivw",         { 2, "", GEN_TO_REG,                    0x4b} },
163   {"udivw",         { 2, "", GEN_TO_REG,                    0x49} },
164   {"modw",          { 2, "", GEN_TO_REG,                    0x4c} },
165   {"umodw",         { 2, "", GEN_TO_REG,                    0x4d} },
166 
167 
168   {"addf",          { 2, "", 1,                             0x50} },
169   {"addd",          { 2, "", 1,                             0x51} },
170   {"subf",          { 2, "", 1,                             0x52} },
171   {"subd",          { 2, "", 1,                             0x53} },
172   {"mulf",          { 2, "", 1,                             0x56} },
173   {"muld",          { 2, "", 1,                             0x57} },
174   {"divf",          { 2, "", 1,                             0x58} },
175   {"divd",          { 2, "", 1,                             0x59} },
176 
177 
178   {"cmpb",          { 2, "", UNKNOWN,             0x61} },
179   {"cmph",          { 2, "", UNKNOWN,             0x62} },
180   {"cmpw",          { 2, "", UNKNOWN,             0x60} },
181   {"ucmpb",         { 2, "", UNKNOWN,             0x66} },
182   /* WHY no "ucmph"??? */
183   {"ucmpw",         { 2, "", UNKNOWN,             0x65} },
184   {"xchw",          { 2, "", UNKNOWN,             0x0f} },
185 
186 
187   {"andw",          { 2, "", GEN_TO_REG,                    0x30} },
188   {"orw", { 2, "", GEN_TO_REG,                    0x31} },
189   {"xorw",          { 2, "", GEN_TO_REG,                    0x32} },
190   {"bicw",          { 2, "", GEN_TO_REG,                    0x33} },
191   {"lshlw",         { 2, "", GEN_TO_REG,                    0x38} },
192   {"ashlw",         { 2, "", GEN_TO_REG,                    0x3a} },
193   {"ashll",         { 2, "", GEN_TO_REG,                    0x3c} },
194   {"ashrw",         { 2, "", GEN_TO_REG,                    0x3b} },
195   {"ashrl",         { 2, "", GEN_TO_REG,                    0x3d} },
196   {"rotlw",         { 2, "", GEN_TO_REG,                    0x3e} },
197   {"rotrw",         { 2, "", GEN_TO_REG,                    0x3f} },
198 
199   /* push and pop insns are "going away next release". */
200   {"pushw",         { 2, "", GEN_TO_REG,                    0x0c} },
201   {"popw",          { 2, "", (0x1|0x8|0x10),      0x0d} },
202   {"pusha",         { 2, "", (0x8|0x10),                    0x0e} },
203 
204   {"bitsw",         { 2, "", UNKNOWN,             0x35} },
205   {"bitcw",         { 2, "", UNKNOWN,             0x36} },
206   /* some kind of ibra/dbra insns??*/
207   {"icmpw",         { 2, "", UNKNOWN,             0x67} },
208   {"dcmpw",         { 2, "", (1|4|0x20|0x80|0x400|0x1000),  0x69} },/*FIXME*/
209   {"acmpw",         { 2, "", 1,                             0x6b} },
210 
211   /* Call is written as a 1-op insn, but is always (dis)assembled as a 2-op
212      insn with a 2nd op of tr14.   The assembler will have to grok this.  */
213   {"call",          { 2, "", GEN_TO_REG,                    0x04} },
214   {"call",          { 1, "", GEN_TO_REG,                    0x04} },
215 
216   {"callk",         { 1, "", UNKNOWN,             0x06} },/* system call?*/
217   /* Ret is usually written as a 0-op insn, but gets disassembled as a
218      1-op insn. The operand is always tr15. */
219   {"ret", { 0, "", UNKNOWN,             0x09} },
220   {"ret", { 1, "", UNKNOWN,             0x09} },
221   {"adsf",          { 2, "", (1|2|4),             0x08} },
222   {"retd",          { 2, "", UNKNOWN,             0x0a} },
223   {"btc", { 2, "", UNKNOWN,             0x01} },
224   {"bfc", { 2, "", UNKNOWN,             0x02} },
225   /* Careful: halt is 0x00000000. Jump must have some other (mode?)bit set?? */
226   {"jump",          { 1, "", UNKNOWN,             0x00} },
227   {"btp", { 2, "", UNKNOWN,             0xf00} },
228   /* read control-stack pointer is another 1-or-2 operand insn. */
229   {"rcsp",          { 2, "", UNKNOWN,             0x01f} },
230   {"rcsp",          { 1, "", UNKNOWN,             0x01f} }
231 };
232 
233 /* end: pyramid.opcode.h */
234 /* One day I will have to take the time to find out what operands
235    are valid for these insns, and guess at what they mean.
236 
237    I can't imagine what the "I???" insns (iglob, etc) do.
238 
239    the arithmetic-sounding insns ending in "p" sound awfully like BCD
240    arithmetic insns:
241           dshlp -> Decimal SHift Left Packed
242           dshrp -> Decimal SHift Right Packed
243    and cvtlp would be convert long to packed.
244    I have no idea how the operands are interpreted; but having them be
245    a long register with (address, length) of an in-memory packed BCD operand
246    would not be surprising.
247    They are unlikely to be a packed bcd string: 64 bits of long give
248    is only 15 digits+sign, which isn't enough for COBOL.
249  */
250 #if 0
251   {"wcsp",          { 2, "", UNKNOWN,             0x00} }, /*write csp?*/
252   /* The OSx Operating System Porting Guide claims SSL does things
253      with tr12 (a register reserved to it) to do with static block-structure
254      references.  SSL=Set Static Link?  It's "Going away next release". */
255   {"ssl", { 2, "", UNKNOWN,             0x00} },
256   {"ccmps",         { 2, "", UNKNOWN,             0x00} },
257   {"lcd", { 2, "", UNKNOWN,             0x00} },
258   {"uemul",         { 2, "", UNKNOWN,             0x00} }, /*unsigned emul*/
259   {"srf", { 2, "", UNKNOWN,             0x00} }, /*Gidget time???*/
260   {"mnegp",         { 2, "", UNKNOWN,             0x00} }, /move-neg phys?*/
261   {"ldp", { 2, "", UNKNOWN,             0x00} }, /*load phys?*/
262   {"ldti",          { 2, "", UNKNOWN,             0x00} },
263   {"ldb", { 2, "", UNKNOWN,             0x00} },
264   {"stp", { 2, "", UNKNOWN,             0x00} },
265   {"stti",          { 2, "", UNKNOWN,             0x00} },
266   {"stb", { 2, "", UNKNOWN,             0x00} },
267   {"stu", { 2, "", UNKNOWN,             0x00} },
268   {"addp",          { 2, "", UNKNOWN,             0x00} },
269   {"subp",          { 2, "", UNKNOWN,             0x00} },
270   {"mulp",          { 2, "", UNKNOWN,             0x00} },
271   {"divp",          { 2, "", UNKNOWN,             0x00} },
272   {"dshlp",         { 2, "", UNKNOWN,             0x00} },  /* dec shl packed? */
273   {"dshrp",         { 2, "", UNKNOWN,             0x00} }, /* dec shr packed? */
274   {"movs",          { 2, "", UNKNOWN,             0x00} }, /*move (string?)?*/
275   {"cmpp",          { 2, "", UNKNOWN,             0x00} }, /* cmp phys?*/
276   {"cmps",          { 2, "", UNKNOWN,             0x00} }, /* cmp (string?)?*/
277   {"cvtlp",         { 2, "", UNKNOWN,             0x00} }, /* cvt long to p??*/
278   {"cvtpl",         { 2, "", UNKNOWN,             0x00} }, /* cvt p to l??*/
279   {"dintr",         { 2, "", UNKNOWN,             0x00} }, /* ?? intr ?*/
280   {"rphysw",        { 2, "", UNKNOWN,             0x00} }, /* read phys word?*/
281   {"wphysw",        { 2, "", UNKNOWN,             0x00} }, /* write phys word?*/
282   {"cmovs",         { 2, "", UNKNOWN,             0x00} },
283   {"rsubw",         { 2, "", UNKNOWN,             0x00} },
284   {"bicpsw",        { 2, "", UNKNOWN,             0x00} }, /* clr bit in psw? */
285   {"bispsw",        { 2, "", UNKNOWN,             0x00} }, /* set bit in psw? */
286   {"eio", { 2, "", UNKNOWN,             0x00} }, /* ?? ?io ? */
287   {"callp",         { 2, "", UNKNOWN,             0x00} }, /* call phys?*/
288   {"callr",         { 2, "", UNKNOWN,             0x00} },
289   {"lpcxt",         { 2, "", UNKNOWN,             0x00} }, /*load proc context*/
290   {"rei", { 2, "", UNKNOWN,             0x00} }, /*ret from intrpt*/
291   {"rport",         { 2, "", UNKNOWN,             0x00} }, /*read-port?*/
292   {"rtod",          { 2, "", UNKNOWN,             0x00} }, /*read-time-of-day?*/
293   {"ssi", { 2, "", UNKNOWN,             0x00} },
294   {"vtpa",          { 2, "", UNKNOWN,             0x00} }, /*virt-to-phys-addr?*/
295   {"wicl",          { 2, "", UNKNOWN,             0x00} }, /* write icl ? */
296   {"wport",         { 2, "", UNKNOWN,             0x00} }, /*write-port?*/
297   {"wtod",          { 2, "", UNKNOWN,             0x00} }, /*write-time-of-day?*/
298   {"flic",          { 2, "", UNKNOWN,             0x00} },
299   {"iglob",         { 2, "", UNKNOWN,             0x00} }, /* I global? */
300   {"iphys",         { 2, "", UNKNOWN,             0x00} }, /* I physical? */
301   {"ipid",          { 2, "", UNKNOWN,             0x00} }, /* I pid? */
302   {"ivect",         { 2, "", UNKNOWN,             0x00} }, /* I vector? */
303   {"lamst",         { 2, "", UNKNOWN,             0x00} },
304   {"tio", { 2, "", UNKNOWN,             0x00} },
305 #endif
306