1: \ disasm.fs disassembler file (for MIPS R3000)
2: \
3: \ Copyright (C) 2000 Free Software Foundation, Inc.
4:
5: \ This file is part of Gforth.
6:
7: \ Gforth is free software; you can redistribute it and/or
8: \ modify it under the terms of the GNU General Public License
9: \ as published by the Free Software Foundation; either version 2
10: \ of the License, or (at your option) any later version.
11:
12: \ This program is distributed in the hope that it will be useful,
13: \ but WITHOUT ANY WARRANTY; without even the implied warranty of
14: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: \ GNU General Public License for more details.
16:
17: \ You should have received a copy of the GNU General Public License
18: \ along with this program; if not, write to the Free Software
19: \ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20:
21: \ this disassembler is based on data from the R4400 manual
22: \ http://www.mips.com/Documentation/R4400_Uman_book_Ed2.pdf, in
23: \ particular pages A3, A181, A182 (p. 471, 649, 650 in xpdf).
24: \ it is limited to the R3000 (MIPS-I) architecture, though.
25:
26: \ test this with
27: \ gforth arch/mips/disasm.fs -e "here" arch/mips/testdisasm.fs -e "here over - disasm bye" |sed 's/([^)]*) //'|diff -u - arch/mips/testasm.fs
28:
29: get-current
30: vocabulary disassembler
31: also disassembler definitions
32:
33: \ instruction fields
34:
35: : disasm-op ( w -- u )
36: 26 rshift ;
37:
38: : disasm-rs ( w -- u )
39: 21 rshift $1F and ;
40:
41: : disasm-rt ( w -- u )
42: 16 rshift $1f and ;
43:
44: : disasm-rd ( w -- u )
45: 11 rshift $1f and ;
46:
47: : disasm-shamt ( w -- u )
48: \ shift amount field
49: 6 rshift $1f and ;
50:
51: : disasm-funct ( w -- u )
52: $3f and ;
53:
54: : disasm-copz ( w -- u )
55: disasm-op 3 and ;
56:
57: : disasm-uimm ( w -- u )
58: $ffff and ;
59:
60: : disasm-imm ( w -- n )
61: disasm-uimm dup 15 rshift negate 15 lshift or ;
62:
63: : disasm-relative ( addr n -- w )
64: \ compute printable form of relative address n relative to addr
65: 2 lshift nip ( + ) ;
66:
67: \ decode tables
68:
69: : disasm-illegal ( addr w -- )
70: \ disassemble illegal/unknown instruction w at addr
71: hex. ." , ( illegal inst ) " drop ;
72:
73: : disasm-table ( n "name" -- )
74: \ initialize table with n entries with disasm-illegal
75: create 0 ?do
76: ['] disasm-illegal ,
77: loop
78: does> ( u -- addr )
79: swap cells + ;
80:
81: $40 disasm-table opc-tab-entry \ top-level decode table
82: $40 disasm-table funct-tab-entry \ special function table
83: $20 disasm-table regimm-tab-entry \ regim instructions rt table
84: $20 disasm-table copz-rs-tab-entry \ COPz instructions rs table
85: $20 disasm-table copz-rt-tab-entry \ COPz BC instructions rt table
86: $40 disasm-table cp0-tab-entry \ COP0 CO instructions funct table
87:
88: \ disassembler central decode cascade
89:
90: dup set-current
91:
92: : disasm-inst ( addr w -- )
93: \G disassemble instruction w at addr (addr is used for computing
94: \G branch targets)
95: dup disasm-op opc-tab-entry @ execute ;
96:
97: : disasm ( addr u -- ) \ gforth
98: \G disassemble u aus starting at addr
99: bounds u+do
100: cr ." ( " i hex. ." ) " i i @ disasm-inst
101: 1 cells +loop
102: cr ;
103:
104: ' disasm IS discode
105:
106: definitions
107:
108: : disasm-special ( addr w -- )
109: \ disassemble inst with opcode special
110: dup disasm-funct funct-tab-entry @ execute ;
111: ' disasm-special 0 opc-tab-entry ! \ enter it for opcode special
112:
113: : disasm-regimm ( addr w -- )
114: \ disassemble regimm inst
115: dup disasm-rt regimm-tab-entry @ execute ;
116: ' disasm-regimm 1 opc-tab-entry ! \ enter it for opcode regimm
117:
118: : disasm-copz-rs ( addr w -- )
119: \ disassemble inst with opcode COPz
120: dup disasm-rs copz-rs-tab-entry @ execute ;
121: ' disasm-copz-rs $10 opc-tab-entry ! \ enter it for opcodes COPz
122: ' disasm-copz-rs $11 opc-tab-entry !
123: ' disasm-copz-rs $12 opc-tab-entry !
124:
125: : disasm-copz-rt ( addr w -- )
126: \ disassemble inst with opcode COPz, rs=BC
127: dup disasm-rt copz-rt-tab-entry @ execute ;
128: ' disasm-copz-rt $08 copz-rs-tab-entry ! \ into COPz-table for rs=BC
129:
130: : disasm-cp0 ( addr w -- )
131: \ disassemble inst with opcode COPz, rs=CO
132: dup disasm-funct cp0-tab-entry @ execute ;
133: ' disasm-cp0 $10 copz-rs-tab-entry ! \ into COPz-table for rs=CO
134:
135: \ dummy words for insts.fs (words with these names are needed by asm.fs)
136:
137: : asm-op ( -- ) ;
138: : asm-rs ( -- ) ;
139: : asm-rt ( -- ) ;
140:
141: \ disassemble various formats
142:
143: : disasm-J-target ( addr w -- )
144: \ print jump target
145: 2 lshift $0fffffff and swap $f0000000 and or hex. ;
146:
147: : disasm-I-rs,rt,imm ( addr w -- )
148: dup disasm-rs .
149: dup disasm-rt .
150: disasm-imm disasm-relative . ;
151:
152: : disasm-I-rs,imm ( addr w -- )
153: dup disasm-rs .
154: disasm-imm disasm-relative . ;
155:
156: : disasm-rt,rs,imm ( addr w -- )
157: dup disasm-rt .
158: dup disasm-rs .
159: disasm-imm .
160: drop ;
161:
162: : disasm-rt,rs,uimm ( addr w -- )
163: dup disasm-rt .
164: dup disasm-rs .
165: disasm-uimm hex.
166: drop ;
167:
168: : disasm-rt,uimm ( addr w -- )
169: dup disasm-rt .
170: disasm-uimm hex.
171: drop ;
172:
173: : disasm-rt,imm,rs ( addr w -- )
174: dup disasm-rt .
175: dup disasm-imm .
176: dup disasm-rs .
177: 2drop ;
178:
179: : disasm-rd,rt,sa ( addr w -- )
180: dup disasm-rd .
181: dup disasm-rt .
182: dup disasm-shamt .
183: 2drop ;
184:
185: : disasm-rd,rt,rs ( addr w -- )
186: dup disasm-rd .
187: dup disasm-rt .
188: dup disasm-rs .
189: 2drop ;
190:
191: : disasm-rs. ( addr w -- )
192: dup disasm-rs .
193: 2drop ;
194:
195: : disasm-rd,rs ( addr w -- )
196: dup disasm-rd .
197: dup disasm-rs .
198: 2drop ;
199:
200: : disasm-rd. ( addr w -- )
201: dup disasm-rd .
202: 2drop ;
203:
204: : disasm-rs,rt ( addr w -- )
205: dup disasm-rs .
206: dup disasm-rt .
207: 2drop ;
208:
209: : disasm-rd,rs,rt ( addr w -- )
210: dup disasm-rd .
211: dup disasm-rs .
212: dup disasm-rt .
213: 2drop ;
214:
215: : disasm-rt,rd,z ( addr w -- )
216: dup disasm-rt .
217: dup disasm-rd .
218: dup disasm-copz .
219: 2drop ;
220:
221: : disasm-I-imm,z ( addr w -- )
222: tuck disasm-imm disasm-relative .
223: disasm-copz . ;
224:
225: \ meta-defining word for instruction format disassembling definitions
226:
227: \ The following word defines instruction-format words, which in turn
228: \ define anonymous words for disassembling specific instructions and
229: \ put them in the appropriate decode table.
230:
231: : define-format ( disasm-xt table-xt -- )
232: \ define an instruction format that uses disasm-xt for
233: \ disassembling and enters the defined instructions into table
234: \ table-xt
235: create 2,
236: does> ( u "inst" -- )
237: \ defines an anonymous word for disassembling instruction inst,
238: \ and enters it as u-th entry into table-xt
239: 2@ swap here name string, ( u table-xt disasm-xt c-addr ) \ remember string
240: noname create 2, \ define anonymous word
241: execute lastxt swap ! \ enter xt of defined word into table-xt
242: does> ( addr w -- )
243: \ disassemble instruction w at addr
244: 2@ >r ( addr w disasm-xt R: c-addr )
245: execute ( R: c-addr ) \ disassemble operands
246: r> count type ; \ print name
247:
248: \ all the following words have the stack effect ( u "name" )
249: ' disasm-J-target ' opc-tab-entry define-format asm-J-target
250: ' disasm-I-rs,rt,imm ' opc-tab-entry define-format asm-I-rs,rt,imm
251: ' disasm-I-rs,imm ' opc-tab-entry define-format asm-I-rs,imm1
252: ' disasm-rt,rs,imm ' opc-tab-entry define-format asm-I-rt,rs,imm
253: ' disasm-rt,rs,uimm ' opc-tab-entry define-format asm-I-rt,rs,uimm
254: ' disasm-rt,uimm ' opc-tab-entry define-format asm-I-rt,uimm
255: ' disasm-rt,imm,rs ' opc-tab-entry define-format asm-I-rt,offset,rs
256: ' disasm-rd,rt,sa ' funct-tab-entry define-format asm-special-rd,rt,sa
257: ' disasm-rd,rt,rs ' funct-tab-entry define-format asm-special-rd,rt,rs
258: ' disasm-rs. ' funct-tab-entry define-format asm-special-rs
259: ' disasm-rd,rs ' funct-tab-entry define-format asm-special-rd,rs
260: ' 2drop ' funct-tab-entry define-format asm-special-nothing
261: ' disasm-rd. ' funct-tab-entry define-format asm-special-rd
262: ' disasm-rs,rt ' funct-tab-entry define-format asm-special-rs,rt
263: ' disasm-rd,rs,rt ' funct-tab-entry define-format asm-special-rd,rs,rt
264: ' disasm-I-rs,imm ' regimm-tab-entry define-format asm-regimm-rs,imm
265: ' 2drop ' cp0-tab-entry define-format asm-copz0
266: ' disasm-rt,rd,z ' copz-rs-tab-entry define-format asm-copz-rt,rd1
267: ' disasm-I-imm,z ' copz-rt-tab-entry define-format asm-copz-imm1
268:
269: : asm-I-rs,imm ( u1 u2 "name" -- ; compiled code: addr w -- )
270: nip asm-I-rs,imm1 ;
271:
272: : asm-copz-rt,rd ( u1 u2 "name" -- )
273: drop asm-copz-rt,rd1 ;
274:
275: : asm-copz-rt,offset,rs ( u "name" -- )
276: \ ignore these insts, we disassemble using asm-I-rt,offset,rs
277: drop name 2drop ;
278:
279: : asm-copz-imm ( u1 u2 u3 "name" -- )
280: drop nip asm-copz-imm1 ;
281:
282: include ./insts.fs
283:
284: previous set-current
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>