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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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