7
7
* Copyright (C) 2005, 2006 by Ralf Baechle ([email protected] )
8
8
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9
9
* Copyright (C) 2004 Thiemo Seufer
10
+ * Copyright (C) 2013 Imagination Technologies Ltd.
10
11
*/
11
12
#include <linux/errno.h>
12
13
#include <linux/sched.h>
@@ -243,34 +244,115 @@ struct mips_frame_info {
243
244
244
245
static inline int is_ra_save_ins (union mips_instruction * ip )
245
246
{
247
+ #ifdef CONFIG_CPU_MICROMIPS
248
+ union mips_instruction mmi ;
249
+
250
+ /*
251
+ * swsp ra,offset
252
+ * swm16 reglist,offset(sp)
253
+ * swm32 reglist,offset(sp)
254
+ * sw32 ra,offset(sp)
255
+ * jradiussp - NOT SUPPORTED
256
+ *
257
+ * microMIPS is way more fun...
258
+ */
259
+ if (mm_insn_16bit (ip -> halfword [0 ])) {
260
+ mmi .word = (ip -> halfword [0 ] << 16 );
261
+ return ((mmi .mm16_r5_format .opcode == mm_swsp16_op &&
262
+ mmi .mm16_r5_format .rt == 31 ) ||
263
+ (mmi .mm16_m_format .opcode == mm_pool16c_op &&
264
+ mmi .mm16_m_format .func == mm_swm16_op ));
265
+ }
266
+ else {
267
+ mmi .halfword [0 ] = ip -> halfword [1 ];
268
+ mmi .halfword [1 ] = ip -> halfword [0 ];
269
+ return ((mmi .mm_m_format .opcode == mm_pool32b_op &&
270
+ mmi .mm_m_format .rd > 9 &&
271
+ mmi .mm_m_format .base == 29 &&
272
+ mmi .mm_m_format .func == mm_swm32_func ) ||
273
+ (mmi .i_format .opcode == mm_sw32_op &&
274
+ mmi .i_format .rs == 29 &&
275
+ mmi .i_format .rt == 31 ));
276
+ }
277
+ #else
246
278
/* sw / sd $ra, offset($sp) */
247
279
return (ip -> i_format .opcode == sw_op || ip -> i_format .opcode == sd_op ) &&
248
280
ip -> i_format .rs == 29 &&
249
281
ip -> i_format .rt == 31 ;
282
+ #endif
250
283
}
251
284
252
285
static inline int is_jal_jalr_jr_ins (union mips_instruction * ip )
253
286
{
287
+ #ifdef CONFIG_CPU_MICROMIPS
288
+ /*
289
+ * jr16,jrc,jalr16,jalr16
290
+ * jal
291
+ * jalr/jr,jalr.hb/jr.hb,jalrs,jalrs.hb
292
+ * jraddiusp - NOT SUPPORTED
293
+ *
294
+ * microMIPS is kind of more fun...
295
+ */
296
+ union mips_instruction mmi ;
297
+
298
+ mmi .word = (ip -> halfword [0 ] << 16 );
299
+
300
+ if ((mmi .mm16_r5_format .opcode == mm_pool16c_op &&
301
+ (mmi .mm16_r5_format .rt & mm_jr16_op ) == mm_jr16_op ) ||
302
+ ip -> j_format .opcode == mm_jal32_op )
303
+ return 1 ;
304
+ if (ip -> r_format .opcode != mm_pool32a_op ||
305
+ ip -> r_format .func != mm_pool32axf_op )
306
+ return 0 ;
307
+ return (((ip -> u_format .uimmediate >> 6 ) & mm_jalr_op ) == mm_jalr_op );
308
+ #else
254
309
if (ip -> j_format .opcode == jal_op )
255
310
return 1 ;
256
311
if (ip -> r_format .opcode != spec_op )
257
312
return 0 ;
258
313
return ip -> r_format .func == jalr_op || ip -> r_format .func == jr_op ;
314
+ #endif
259
315
}
260
316
261
317
static inline int is_sp_move_ins (union mips_instruction * ip )
262
318
{
319
+ #ifdef CONFIG_CPU_MICROMIPS
320
+ /*
321
+ * addiusp -imm
322
+ * addius5 sp,-imm
323
+ * addiu32 sp,sp,-imm
324
+ * jradiussp - NOT SUPPORTED
325
+ *
326
+ * microMIPS is not more fun...
327
+ */
328
+ if (mm_insn_16bit (ip -> halfword [0 ])) {
329
+ union mips_instruction mmi ;
330
+
331
+ mmi .word = (ip -> halfword [0 ] << 16 );
332
+ return ((mmi .mm16_r3_format .opcode == mm_pool16d_op &&
333
+ mmi .mm16_r3_format .simmediate && mm_addiusp_func ) ||
334
+ (mmi .mm16_r5_format .opcode == mm_pool16d_op &&
335
+ mmi .mm16_r5_format .rt == 29 ));
336
+ }
337
+ return (ip -> mm_i_format .opcode == mm_addiu32_op &&
338
+ ip -> mm_i_format .rt == 29 && ip -> mm_i_format .rs == 29 );
339
+ #else
263
340
/* addiu/daddiu sp,sp,-imm */
264
341
if (ip -> i_format .rs != 29 || ip -> i_format .rt != 29 )
265
342
return 0 ;
266
343
if (ip -> i_format .opcode == addiu_op || ip -> i_format .opcode == daddiu_op )
267
344
return 1 ;
345
+ #endif
268
346
return 0 ;
269
347
}
270
348
271
349
static int get_frame_info (struct mips_frame_info * info )
272
350
{
351
+ #ifdef CONFIG_CPU_MICROMIPS
352
+ union mips_instruction * ip = (void * ) (((char * ) info -> func ) - 1 );
353
+ #else
273
354
union mips_instruction * ip = info -> func ;
355
+ #endif
274
356
unsigned max_insns = info -> func_size / sizeof (union mips_instruction );
275
357
unsigned i ;
276
358
@@ -290,7 +372,26 @@ static int get_frame_info(struct mips_frame_info *info)
290
372
break ;
291
373
if (!info -> frame_size ) {
292
374
if (is_sp_move_ins (ip ))
375
+ {
376
+ #ifdef CONFIG_CPU_MICROMIPS
377
+ if (mm_insn_16bit (ip -> halfword [0 ]))
378
+ {
379
+ unsigned short tmp ;
380
+
381
+ if (ip -> halfword [0 ] & mm_addiusp_func )
382
+ {
383
+ tmp = (((ip -> halfword [0 ] >> 1 ) & 0x1ff ) << 2 );
384
+ info -> frame_size = - (signed short )(tmp | ((tmp & 0x100 ) ? 0xfe00 : 0 ));
385
+ } else {
386
+ tmp = (ip -> halfword [0 ] >> 1 );
387
+ info -> frame_size = - (signed short )(tmp & 0xf );
388
+ }
389
+ ip = (void * ) & ip -> halfword [1 ];
390
+ ip -- ;
391
+ } else
392
+ #endif
293
393
info -> frame_size = - ip -> i_format .simmediate ;
394
+ }
294
395
continue ;
295
396
}
296
397
if (info -> pc_offset == -1 && is_ra_save_ins (ip )) {
0 commit comments