OpenCores
URL https://opencores.org/ocsvn/ion/ion/trunk

Subversion Repositories ion

[/] [ion/] [trunk/] [src/] [common/] [opcode_emu.s] - Blame information for rev 166

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 165 ja_rd
#-------------------------------------------------------------------------------
2
# opcode_emu.s -- Emulation of some mips-32 opcodes in trap handler
3
#
4
# Operation:
5
# 1.- If the trapped opcode is one of the emulated opcodes, it is emulated.
6
# 2.- Otherwise, nothing is done (as if the trapped opcode was a NOP) and a flag
7
#     is set in the emu_frame area (meant for debugging, mostly).
8
# 3.- In either case, if the trapped opcode is in a jump delay slot, the jump
9
#     instruction is emulated. FIXME it isn't yet
10
#
11
# Uses a small workspace in the BSS section. Does NOT use the regular stack
12
# nor makes any assumptions about any registers, including the sp.
13
#
14
#-------------------------------------------------------------------------------
15
# This is a trap handler meant to emulate those few MIPS32r1/r2 opcodes that
16
# gcc commonly emits even for a -mips1 target. This happens specially when using
17
# soft floating point.
18
# The opcodes chosen for emulation are those actually observed in real gcc
19
# programs. This is easier, for the time being, than replacing a whole host of
20
# gcc support functions.
21
#
22
# Emulates the following opcodes:
23
#   EXT, INS, CLO, CLZ
24
#
25
# FIXME these opcodes will be emulated eventually:
26
#   MUL (3-reg version), LWL, LWR, SWL, SWR
27
#-------------------------------------------------------------------------------
28
 
29
    # Size of work space
30
    .set EMU_FRAME_SIZE, 64
31
 
32
    # Reserve work space in BSS segment
33
    .comm emu_frame, EMU_FRAME_SIZE
34
 
35
    .text
36
    .align  2
37
    .set    noreorder
38
 
39
    .global opcode_emu
40
    # $k0 = cp0.cause on entry, other registers have their original value
41
opcode_emu:
42
    # Save the CPU state.
43
    # No nested exceptions are to be allowed, so we only save the registers
44
    # we're going to use and leave the CP0 registers unsaved.
45
    la      $k1,emu_frame+EMU_FRAME_SIZE-4
46
    sw      $sp,-16($k1)
47
    sw      $ra,-20($k1)
48
    sw      $t0,-24($k1)
49
    sw      $t1,-28($k1)
50
    sw      $t2,-32($k1)
51
    move    $sp,$k1
52
 
53
    # FIXME handle delay slot situation: emulate jump if necessary
54
 
55
    # get bad opcode
56
    mfc0    $t0,$14
57
    lw      $k0,0($t0)
58
    # decode instruction: either SPECIAL3 or SPECIAL2
59
    srl     $t1,$k0,26
60
    xori    $t0,$t1,0x01f
61
    beqz    $t0,mips32_special3
62
    xori    $t0,$t1,0x01c
63
    beqz    $t0,mips32_special2
64
    nop
65
    # if it was none of the above we will just ignore it
66
    # Write ignored opcode to some debug register for external reference
67
    # (this is to be used bu the SW simulator, mostly)
68
    li      $t0,0x20010000
69
    sw      $k0,1024($t0)
70
    # Run into opcode_emu_return
71
 
72
opcode_emu_return:
73
    # restore modified registers
74
    lw      $t2,-32($sp)
75
    lw      $t1,-28($sp)
76
    lw      $t0,-24($sp)
77
    lw      $ra,-20($sp)
78
    lw      $sp,-16($sp)
79
    # return to interrupted code, handling trap-in-delay-slot cases properly
80
    mfc0    $k1,$14             # C0_EPC=14 (Exception PC)
81
    mfc0    $k0,$13             # Get bit 31 (BD) from C0 cause register
82
    srl     $k0,31
83
    andi    $k0,$k0,1
84
    bnez    $k0,mips32_emu_return_delay_slot
85
    addi    $k1,$k1,4           # skip 'victim' instruction
86
    jr      $k1
87
    nop
88
mips32_emu_return_delay_slot:
89
    addi    $k1,$k1,4           # skip jump instruction too (it's been emulated)
90
    jr      $k1                 # (we just added 8 to epc)
91
    rfe
92
 
93
    # SPECIAL2 opcodes
94
    # entry: k0=opcode
95
mips32_special2:
96
    andi    $k1,$k0,0x03f
97
    xori    $t0,$k1,0x020
98
    beqz    $t0,mips32_CLZ
99
    xori    $t0,$k1,0x021
100
    beqz    $t0,mips32_CLO
101
    nop
102
    # all other special-3 opcodes go unemulated
103
    li      $t0,0x20010000      # Write ignored opcode to debug register
104
    sw      $k0,1024($t0)
105
    j       opcode_emu_return
106
    nop
107
 
108
    # SPECIAL3 opcodes
109
    # $k0 = opcode
110
mips32_special3:
111
    andi    $k1,$k0,0x03f
112
    xori    $t0,$k1,0x0
113
    beqz    $t0,mips32_EXT
114
    xori    $t0,$k1,0x04
115
    beqz    $t0,mips32_INS
116
    nop
117
    # all other special-3 opcodes go unemulated
118
    li      $t0,0x20010000      # Write ignored opcode to debug register
119
    sw      $k0,1024($t0)
120
    j       opcode_emu_return
121
    nop
122
 
123
    #---- Opcode emulation routines --------------------------------------------
124
 
125
    # CLZ: rd <- count leading zeros on rs
126
mips32_CLZ:
127
    jal     get_source_register             # $k1 = source register (Rs)
128
    lui     $t2,0x8000                      # $t2 = bit mask
129
 
130
    move    $t0,$zero                       # $t0 = counter
131
mips32_clz_loop:
132
    and     $t1,$k1,$t2
133
    bnez    $t1,mips32_clz_done
134
    srl     $t2,$t2,1
135
    bnez    $t2,mips32_clz_loop
136
    addiu   $t0,$t0,1
137
mips32_clz_done:
138
    j       mips32_save_result              # put result in dest reg and return
139
    move    $k1,$t0
140
 
141
    # CLO: rd <- count leading ones on rs
142
mips32_CLO:
143
    jal     get_source_register             # $k1 = source register (Rs)
144
    lui     $t2,0x8000                      # $t2 = bit mask
145
 
146
    move    $t0,$zero                       # $t0 = counter
147
mips32_clo_loop:
148
    and     $t1,$k1,$t2
149
    beqz    $t1,mips32_clo_done
150
    srl     $t2,$t2,1
151
    bnez    $t2,mips32_clo_loop
152
    addiu   $t0,$t0,1
153
mips32_clo_done:
154
    j       mips32_save_result              # put result in dest reg and return
155
    move    $k1,$t0
156
 
157
    # EXT:
158
mips32_EXT:
159
    jal     get_source_register             # $k1 = source register (Rs)
160
    nop
161
    srl     $t0,$k0,6                       # $t0 = pos
162
    andi    $t0,$t0,0x1f
163
    srl     $t1,$k0,11
164
    andi    $t1,$t1,0x1f                    # $t1 = size-1
165
 
166
    addu    $t2,$t0,$t1                     # ...by shifting left and then right
167
    subu    $t2,$zero,$t2
168
    addiu   $t2,$t2,31
169
    sllv    $k1,$k1,$t2
170
    srlv    $k1,$k1,$t2
171
    j       mips32_save_result              # put result in dest reg and return
172
    srlv    $k1,$k1,$t0                     # k1 = bit field, zero extended
173
 
174
    # INS:
175
mips32_INS:
176
    jal     get_source_register             # $k1 = source register (Rs)
177
    nop
178
 
179
    srl     $t0,$k0,6                       # $t0 = pos
180
    andi    $t0,$t0,0x1f
181
    srl     $t1,$k0,11
182
    andi    $t1,$t1,0x1f                    # $t1 = pos+size-1
183
    subu    $t1,$t1,$t0                     # $t1 = size-1
184
 
185
    subu    $t3,$zero,$t1                   # $t1 = source bit field, shifted
186
    addiu   $t3,$t3,31
187
    sllv    $t1,$k1,$t0
188
 
189
    lui     $t2,0xffff                      # $t2 = target mask (0 for bitfield)
190
    ori     $t2,$t2,0xffff
191
    sllv    $t2,$t2,$t3
192
    srlv    $t2,$t2,$t3
193
    sllv    $t2,$t2,$t0
194
    and     $t1,$t1,$t2                     # $t1 = source bit field, masked
195
    not     $t2,$t2
196
 
197
    # ok, we're done with the source register, and we have the following:
198
    # $t0=pos, $t1=size-1, $t3=left shift amount, $t4=bitfield, $t2=mask
199
 
200
    # (uses $k1 and $t0)
201
    jal     get_source_register             # $k1 = target register
202
    sll     $k0,$k0,5
203
    srl     $k0,$k0,5                       # restore field Rt of opcode
204
 
205
    and     $k1,$k1,$t2                     # insert bit field in Rt...
206
    or      $k1,$k1,$t1
207
 
208
    j       mips32_save_result              # ...and put result back in register
209
    nop
210
 
211
 
212
    #---- Common utility routines ----------------------------------------------
213
 
214
    # entry: $k0 = opcode, $k1 = result
215
mips32_save_result:
216
    srl     $t1,$k0,16
217
    andi    $t1,$t1,0x1f
218
    la      $t0,set_target_table
219
    sll     $t1,$t1,3
220
    add     $t0,$t1
221
    jr      $t0
222
    nop
223
set_target_done:
224
    j       opcode_emu_return
225
    nop
226
 
227
set_target_table:
228
    j       set_target_done
229
    ori     $0,$k1,0
230
    j       set_target_done
231
    ori     $1,$k1,0
232
    j       set_target_done
233
    ori     $2,$k1,0
234
    j       set_target_done
235
    ori     $3,$k1,0
236
    j       set_target_done
237
    ori     $4,$k1,0
238
    j       set_target_done
239
    ori     $5,$k1,0
240
    j       set_target_done
241
    ori     $6,$k1,0
242
    j       set_target_done
243
    ori     $7,$k1,0
244
    j       set_target_done
245
    sw      $k1,-24($sp)
246
    j       set_target_done
247
    sw      $k1,-28($sp)
248
    j       set_target_done
249
    sw      $k1,-32($sp)
250
    j       set_target_done
251
    ori     $11,$k1,0
252
    j       set_target_done
253
    ori     $12,$k1,0
254
    j       set_target_done
255
    ori     $13,$k1,0
256
    j       set_target_done
257
    ori     $14,$k1,0
258
    j       set_target_done
259
    ori     $15,$k1,0
260
    j       set_target_done
261
    ori     $16,$k1,0
262
    j       set_target_done
263
    ori     $17,$k1,0
264
    j       set_target_done
265
    ori     $18,$k1,0
266
    j       set_target_done
267
    ori     $19,$k1,0
268
    j       set_target_done
269
    ori     $20,$k1,0
270
    j       set_target_done
271
    ori     $21,$k1,0
272
    j       set_target_done
273
    ori     $22,$k1,0
274
    j       set_target_done
275
    ori     $23,$k1,0
276
    j       set_target_done
277
    ori     $24,$k1,0
278
    j       set_target_done
279
    ori     $25,$k1,0
280
    j       set_target_done
281
    ori     $26,$k1,0
282
    j       set_target_done
283
    ori     $27,$k1,0
284
    j       set_target_done
285
    ori     $28,$k1,0
286
    j       set_target_done
287
    sw      $k1,-20($sp)
288
    j       set_target_done
289
    ori     $30,$k1,0
290
    j       set_target_done
291
    sw      $k1,-16($sp)
292
 
293
    # get value of register rs (field 25..21)
294
    # entry: $k0=opcode
295
    # exit: $k1=source
296
get_source_register:
297
    sw      $ra,0($sp)
298
    srl     $k1,$k0,21
299
    andi    $k1,$k1,0x1f
300
    la      $t0,get_source_table
301
    sll     $k1,$k1,3
302
    add     $t0,$t0,$k1
303
    jalr    $t0
304
    nop
305
    lw      $ra,0($sp)
306
    jr      $ra
307
    nop
308
 
309
    # exit: $k1=source reg
310
get_source_table:
311
    jr      $ra
312
    ori     $k1,$0,0
313
    jr      $ra
314
    ori     $k1,$1,0
315
    jr      $ra
316
    ori     $k1,$2,0
317
    jr      $ra
318
    ori     $k1,$3,0
319
    jr      $ra
320
    ori     $k1,$4,0
321
    jr      $ra
322
    ori     $k1,$5,0
323
    jr      $ra
324
    ori     $k1,$6,0
325
    jr      $ra
326
    ori     $k1,$7,0
327
    jr      $ra
328
    lw      $k1,-24($sp)
329
    jr      $ra
330
    lw      $k1,-28($sp)
331
    jr      $ra
332
    lw      $k1,-32($sp)
333
    jr      $ra
334
    ori     $k1,$11,0
335
    jr      $ra
336
    ori     $k1,$12,0
337
    jr      $ra
338
    ori     $k1,$13,0
339
    jr      $ra
340
    ori     $k1,$14,0
341
    jr      $ra
342
    ori     $k1,$15,0
343
    jr      $ra
344
    ori     $k1,$16,0
345
    jr      $ra
346
    ori     $k1,$17,0
347
    jr      $ra
348
    ori     $k1,$18,0
349
    jr      $ra
350
    ori     $k1,$19,0
351
    jr      $ra
352
    ori     $k1,$20,0
353
    jr      $ra
354
    ori     $k1,$21,0
355
    jr      $ra
356
    ori     $k1,$22,0
357
    jr      $ra
358
    ori     $k1,$23,0
359
    jr      $ra
360
    ori     $k1,$24,0
361
    jr      $ra
362
    ori     $k1,$25,0
363
    jr      $ra
364
    ori     $k1,$26,0
365
    jr      $ra
366
    ori     $k1,$27,0
367
    jr      $ra
368
    ori     $k0,$28,0
369
    jr      $ra
370
    lw      $k1,-16($sp)
371
    jr      $ra
372
    ori     $k1,$30,0
373
    jr      $ra
374
    lw      $k1,-20($sp)
375
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.