~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/nios2/kernel/insnemu.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/nios2/kernel/insnemu.S (Version linux-6.12-rc7) and /arch/i386/kernel/insnemu.S (Version linux-4.15.18)


  1 /* SPDX-License-Identifier: GPL-2.0-or-later *    
  2 /*                                                
  3  *  Copyright (C) 2003-2013 Altera Corporation    
  4  *  All rights reserved.                          
  5  */                                               
  6                                                   
  7                                                   
  8 #include <linux/linkage.h>                        
  9 #include <asm/entry.h>                            
 10                                                   
 11 .set noat                                         
 12 .set nobreak                                      
 13                                                   
 14 /*                                                
 15 * Explicitly allow the use of r1 (the assemble    
 16 * within this code. This register is normally     
 17 * the compiler.                                   
 18 */                                                
 19                                                   
 20 ENTRY(instruction_trap)                           
 21         ldw     r1, PT_R1(sp)           // Res    
 22         ldw     r2, PT_R2(sp)                     
 23         ldw     r3, PT_R3(sp)                     
 24         ldw     r4, PT_R4(sp)                     
 25         ldw     r5, PT_R5(sp)                     
 26         ldw     r6, PT_R6(sp)                     
 27         ldw     r7, PT_R7(sp)                     
 28         ldw     r8, PT_R8(sp)                     
 29         ldw     r9, PT_R9(sp)                     
 30         ldw     r10, PT_R10(sp)                   
 31         ldw     r11, PT_R11(sp)                   
 32         ldw     r12, PT_R12(sp)                   
 33         ldw     r13, PT_R13(sp)                   
 34         ldw     r14, PT_R14(sp)                   
 35         ldw     r15, PT_R15(sp)                   
 36         ldw     ra, PT_RA(sp)                     
 37         ldw     fp, PT_FP(sp)                     
 38         ldw     gp, PT_GP(sp)                     
 39         ldw     et, PT_ESTATUS(sp)                
 40         wrctl   estatus, et                       
 41         ldw     ea, PT_EA(sp)                     
 42         ldw     et, PT_SP(sp)           /* bac    
 43                                                   
 44         addi    sp, sp, PT_REGS_SIZE              
 45                                                   
 46         /* INSTRUCTION EMULATION                  
 47         *  ---------------------                  
 48         *                                         
 49         * Nios II processors generate exceptio    
 50         * The routines below emulate these ins    
 51         * processor core, the only instruction    
 52         * are div, divu, mul, muli, mulxss, mu    
 53         *                                         
 54         * The emulations match the instruction    
 55         * limitations:                            
 56         *                                         
 57         * 1) The emulation routines do not emu    
 58         *    temporary register (et) as a sour    
 59         *    handler already has modified it.     
 60         *                                         
 61         * 2) The routines do not emulate the u    
 62         *    the exception return address regi    
 63         *    modifying these registers crashes    
 64         *    interrupted routine.                 
 65         *                                         
 66         * Detailed Design                         
 67         * ---------------                         
 68         *                                         
 69         * The emulation routines expect the co    
 70         * to be on the stack at addresses sp,     
 71         * routines retrieve source operands fr    
 72         * destination register's value on the     
 73         * exception handler.  Then all registe    
 74         * are restored to their previous value    
 75         *                                         
 76         * The instruction that causes the exce    
 77         * The instruction's OP and OPX fields     
 78         * performed.                              
 79         *                                         
 80         * One instruction, muli, is an I-type     
 81         * an OP field of 0x24.                    
 82         *                                         
 83         * muli   AAAAA,BBBBB,IIIIIIIIIIIIIIII,    
 84         *           27    22                6     
 85         *                                         
 86         * The remaining emulated instructions     
 87         * of 0x3a.  Their OPX fields identify     
 88         *                                         
 89         * R-type AAAAA,BBBBB,CCCCC,XXXXXX,NNNN    
 90         *           27    22    17     11         
 91         *                                         
 92         *                                         
 93         * Opcode Encoding.  muli is identified    
 94         * is used to differentiate between the    
 95         * remaining multiplication opcodes.       
 96         *                                         
 97         * Instruction   OP      OPX    OPX & 0    
 98         * -----------   ----    ----   -------    
 99         * muli          0x24                      
100         * divu          0x3a    0x24         0    
101         * div           0x3a    0x25         0    
102         * mul           0x3a    0x27      != 0    
103         * mulxuu        0x3a    0x07      != 0    
104         * mulxsu        0x3a    0x17      != 0    
105         * mulxss        0x3a    0x1f      != 0    
106         */                                        
107                                                   
108                                                   
109         /*                                        
110         * Save everything on the stack to make    
111         * routines to retrieve the source regi    
112         */                                        
113                                                   
114         addi sp, sp, -128                         
115         stw zero, 0(sp) /* Save zero on stack     
116         stw r1, 4(sp)                             
117         stw r2,  8(sp)                            
118         stw r3, 12(sp)                            
119         stw r4, 16(sp)                            
120         stw r5, 20(sp)                            
121         stw r6, 24(sp)                            
122         stw r7, 28(sp)                            
123         stw r8, 32(sp)                            
124         stw r9, 36(sp)                            
125         stw r10, 40(sp)                           
126         stw r11, 44(sp)                           
127         stw r12, 48(sp)                           
128         stw r13, 52(sp)                           
129         stw r14, 56(sp)                           
130         stw r15, 60(sp)                           
131         stw r16, 64(sp)                           
132         stw r17, 68(sp)                           
133         stw r18, 72(sp)                           
134         stw r19, 76(sp)                           
135         stw r20, 80(sp)                           
136         stw r21, 84(sp)                           
137         stw r22, 88(sp)                           
138         stw r23, 92(sp)                           
139                 /* Don't bother to save et.  I    
140         rdctl r5, estatus                         
141         stw r5,  100(sp)                          
142                                                   
143         stw gp, 104(sp)                           
144         stw et, 108(sp) /* et contains previou    
145         stw fp, 112(sp)                           
146         stw ea, 116(sp)                           
147         stw ra, 120(sp)                           
148                                                   
149                                                   
150         /*                                        
151         * Split the instruction into its field    
152         * offsets to the stack pointer for acc    
153         */                                        
154         ldw r2,-4(ea)   /* r2 = AAAAA,BBBBB,II    
155         roli r3, r2, 7  /* r3 = BBB,IIIIIIIIII    
156         roli r4, r3, 3  /* r4 = IIIIIIIIIIIIII    
157         roli r5, r4, 2  /* r5 = IIIIIIIIIIIIII    
158         srai r4, r4, 16 /* r4 = (sign-extended    
159         roli r6, r5, 5  /* r6 = XXXX,NNNNN,PPP    
160         andi r2, r2, 0x3f       /* r2 = 000000    
161         andi r3, r3, 0x7c       /* r3 = 000000    
162         andi r5, r5, 0x7c       /* r5 = 000000    
163         andi r6, r6, 0x7c       /* r6 = 000000    
164                                                   
165         /* Now                                    
166         * r2 = OP                                 
167         * r3 = 4*A                                
168         * r4 = IMM16 (sign extended)              
169         * r5 = 4*B                                
170         * r6 = 4*C                                
171         */                                        
172                                                   
173         /*                                        
174         * Get the operands.                       
175         *                                         
176         * It is necessary to check for muli be    
177         * instruction format, while the other     
178         * format.                                 
179         *                                         
180         *  Prepare for either multiplication o    
181         *  They both loop 32 times.               
182         */                                        
183         movi r14, 32                              
184                                                   
185         add  r3, r3, sp         /* r3 = addres    
186         ldw  r3, 0(r3)          /* r3 = A-oper    
187         movi r7, 0x24           /* muli opcode    
188         beq r2, r7, mul_immed /* muli doesn't     
189                                                   
190         add  r5, r5, sp         /* r5 = addres    
191         ldw  r5, 0(r5)          /* r5 = B-oper    
192                                 /* r4 = SSSSSS    
193                                 /* IMM16 not n    
194                                 /* r4 = SSSSSS    
195         srli r4, r4, 5          /* r4 = 00000,    
196         andi r4, r4, 0x3f       /* r4 = 000000    
197                                                   
198         /* Now                                    
199         * r2 = OP                                 
200         * r3 = src1                               
201         * r5 = src2                               
202         * r4 = OPX (no longer can be muli)        
203         * r6 = 4*C                                
204         */                                        
205                                                   
206                                                   
207         /*                                        
208         *  Multiply or Divide?                    
209         */                                        
210         andi r7, r4, 0x02       /* For R-type     
211                                    OPX & 0x02     
212         bne r7, zero, multiply                    
213                                                   
214                                                   
215         /* DIVISION                               
216         *                                         
217         * Divide an unsigned dividend by an un    
218         * a shift-and-subtract algorithm.  The    
219         * 43 div 7 = 6 for 8-bit integers.  Th    
220         * single register to store both the di    
221         * allowing both values to be shifted w    
222         *                                         
223         *                               remain    
224         *                               ------    
225         *   initialize                   00000    
226         *   shift                        00000    
227         *   remainder >= divisor? no     00000    
228         *   shift                        00000    
229         *   remainder >= divisor? no     00000    
230         *   shift                        00000    
231         *   remainder >= divisor? no     00000    
232         *   shift                        00000    
233         *   remainder >= divisor? no     00000    
234         *   shift                        00000    
235         *   remainder >= divisor? no     00000    
236         *   shift                        00001    
237         *   remainder >= divisor? yes    00001    
238         *       remainder -= divisor   - 00000    
239         *                              -------    
240         *                                00000    
241         *   shift                        00000    
242         *   remainder >= divisor? yes    00000    
243         *       remainder -= divisor   - 00000    
244         *                              -------    
245         *                                00000    
246         *   shift                        00000    
247         *   remainder >= divisor? no     00000    
248         *                                         
249         * The quotient is 00000110.               
250         */                                        
251                                                   
252 divide:                                           
253         /*                                        
254         *  Prepare for division by assuming th    
255         *  is unsigned, and storing its "sign"    
256         */                                        
257         movi r17, 0                               
258                                                   
259                                                   
260         /* Which division opcode? */              
261         xori r7, r4, 0x25               /* OPX    
262         bne r7, zero, unsigned_division           
263                                                   
264                                                   
265         /*                                        
266         *  OPX is div.  Determine and store th    
267         *  Then take the absolute value of bot    
268         */                                        
269         xor r17, r3, r5         /* MSB contain    
270         bge r3,zero,dividend_is_nonnegative       
271         sub r3, zero, r3        /* -r3 */         
272 dividend_is_nonnegative:                          
273         bge r5, zero, divisor_is_nonnegative      
274         sub r5, zero, r5        /* -r5 */         
275 divisor_is_nonnegative:                           
276                                                   
277                                                   
278 unsigned_division:                                
279         /* Initialize the unsigned-division lo    
280         movi r13, 0     /* remainder = 0 */       
281                                                   
282         /* Now                                    
283         * r3 = dividend : quotient                
284         * r4 = 0x25 for div, 0x24 for divu        
285         * r5 = divisor                            
286         * r13 = remainder                         
287         * r14 = loop counter (already initiali    
288         * r17 = MSB contains sign of quotient     
289         */                                        
290                                                   
291                                                   
292         /*                                        
293         *   for (count = 32; count > 0; --coun    
294         *   {                                     
295         */                                        
296 divide_loop:                                      
297                                                   
298         /*                                        
299         *       Division:                         
300         *                                         
301         *       (remainder:dividend:quotient)     
302         */                                        
303         slli r13, r13, 1                          
304         cmplt r7, r3, zero      /* r7 = MSB of    
305         or r13, r13, r7                           
306         slli r3, r3, 1                            
307                                                   
308                                                   
309         /*                                        
310         *       if (remainder >= divisor)         
311         *       {                                 
312         *           set LSB of quotient           
313         *           remainder -= divisor;         
314         *       }                                 
315         */                                        
316         bltu r13, r5, div_skip                    
317         ori r3, r3, 1                             
318         sub r13, r13, r5                          
319 div_skip:                                         
320                                                   
321         /*                                        
322         *   }                                     
323         */                                        
324         subi r14, r14, 1                          
325         bne r14, zero, divide_loop                
326                                                   
327                                                   
328         /* Now                                    
329         * r3 = quotient                           
330         * r4 = 0x25 for div, 0x24 for divu        
331         * r6 = 4*C                                
332         * r17 = MSB contains sign of quotient     
333         */                                        
334                                                   
335                                                   
336         /*                                        
337         *  Conditionally negate signed quotien    
338         *  the sign already is initialized to     
339         */                                        
340         bge r17, zero, quotient_is_nonnegative    
341         sub r3, zero, r3                /* -r3    
342         quotient_is_nonnegative:                  
343                                                   
344                                                   
345         /*                                        
346         *  Final quotient is in r3.               
347         */                                        
348         add r6, r6, sp                            
349         stw r3, 0(r6)   /* write quotient to s    
350         br restore_registers                      
351                                                   
352                                                   
353                                                   
354                                                   
355         /* MULTIPLICATION                         
356         *                                         
357         * A "product" is the number that one g    
358         * several times.  The "multiplier" spe    
359         * multiplicand that are summed.           
360         *                                         
361         * Actual multiplication algorithms don    
362         * Shift-and-add algorithms get the sam    
363         * they are faster.  To compute the low    
364         * one shifts the product left before a    
365         * products (a * mmmm) through (d * mmm    
366         *                                         
367         * To compute the upper half of a produ    
368         * partial products (d * mmmm) through     
369         * the add by a right shift of the prod    
370         *                                         
371         *     mmmm                                
372         *   * abcd                                
373         *   ------                                
374         *     ####  = d * mmmm                    
375         *    ####   = c * mmmm                    
376         *   ####    = b * mmmm                    
377         *  ####     = a * mmmm                    
378         * --------                                
379         * PPPPpppp                                
380         *                                         
381         * The example above shows 4 partial pr    
382         * products requires 32 partials.          
383         *                                         
384         * It is possible to compute the result    
385         * mulxuu because the only difference b    
386         * opcodes is the value of the partial     
387         * bit of rA.                              
388         *                                         
389         *   mulxsu = mulxuu - (rA < 0) ? rB :     
390         *                                         
391         * It is possible to compute the result    
392         * mulxsu because the only difference b    
393         * opcodes is the value of the partial     
394         * bit of rB.                              
395         *                                         
396         *   mulxss = mulxsu - (rB < 0) ? rA :     
397         *                                         
398         */                                        
399                                                   
400 mul_immed:                                        
401         /* Opcode is muli.  Change it into mul    
402         mov r6, r5              /* Field B is     
403         mov r5, r4              /* Field IMM16    
404         movi r4, 0x27           /* OPX of mul     
405                                                   
406 multiply:                                         
407         /* Initialize the multiplication loop.    
408         movi r9, 0      /* mul_product    = 0     
409         movi r10, 0     /* mulxuu_product = 0     
410         mov r11, r5     /* save original multi    
411         mov r12, r5     /* mulxuu_multiplier (    
412         movi r16, 1     /* used to create "ror    
413                                                   
414         /* Now                                    
415         * r3 = multiplicand                       
416         * r5 = mul_multiplier                     
417         * r6 = 4 * dest_register (used later a    
418         * r7 = temp                               
419         * r9 = mul_product                        
420         * r10 = mulxuu_product                    
421         * r11 = original multiplier               
422         * r12 = mulxuu_multiplier                 
423         * r14 = loop counter (already initiali    
424         * r16 = 1                                 
425         */                                        
426                                                   
427                                                   
428         /*                                        
429         *   for (count = 32; count > 0; --coun    
430         *   {                                     
431         */                                        
432 multiply_loop:                                    
433                                                   
434         /*                                        
435         *       mul_product <<= 1;                
436         *       lsb = multiplier & 1;             
437         */                                        
438         slli r9, r9, 1                            
439         andi r7, r12, 1                           
440                                                   
441         /*                                        
442         *       if (lsb == 1)                     
443         *       {                                 
444         *           mulxuu_product += multipli    
445         *       }                                 
446         */                                        
447         beq r7, zero, mulx_skip                   
448         add r10, r10, r3                          
449         cmpltu r7, r10, r3 /* Save the carry f    
450         ror r7, r7, r16 /* r7 = 0x80000000 on     
451 mulx_skip:                                        
452                                                   
453         /*                                        
454         *       if (MSB of mul_multiplier == 1    
455         *       {                                 
456         *           mul_product += multiplican    
457         *       }                                 
458         */                                        
459         bge r5, zero, mul_skip                    
460         add r9, r9, r3                            
461 mul_skip:                                         
462                                                   
463         /*                                        
464         *       mulxuu_product >>= 1;             
465         *       mul_multiplier <<= 1;             
466         *       mulx_multiplier >>= 1;            
467         */                                        
468         srli r10, r10, 1                          
469         or r10, r10, r7         /* OR in the s    
470         slli r5, r5, 1                            
471         srli r12, r12, 1                          
472                                                   
473                                                   
474         /*                                        
475         *   }                                     
476         */                                        
477         subi r14, r14, 1                          
478         bne r14, zero, multiply_loop              
479                                                   
480                                                   
481         /*                                        
482         *  Multiply emulation loop done.          
483         */                                        
484                                                   
485         /* Now                                    
486         * r3 = multiplicand                       
487         * r4 = OPX                                
488         * r6 = 4 * dest_register (used later a    
489         * r7 = temp                               
490         * r9 = mul_product                        
491         * r10 = mulxuu_product                    
492         * r11 = original multiplier               
493         */                                        
494                                                   
495                                                   
496         /* Calculate address for result from 4    
497         add r6, r6, sp                            
498                                                   
499                                                   
500         /*                                        
501         * Select/compute the result based on O    
502         */                                        
503                                                   
504                                                   
505         /* OPX == mul?  Then store. */            
506         xori r7, r4, 0x27                         
507         beq r7, zero, store_product               
508                                                   
509         /* It's one of the mulx.. opcodes.  Mo    
510         mov r9, r10                               
511                                                   
512         /* OPX == mulxuu?  Then store. */         
513         xori r7, r4, 0x07                         
514         beq r7, zero, store_product               
515                                                   
516         /* Compute mulxsu                         
517          *                                        
518          * mulxsu = mulxuu - (rA < 0) ? rB : 0    
519          */                                       
520         bge r3, zero, mulxsu_skip                 
521         sub r9, r9, r11                           
522 mulxsu_skip:                                      
523                                                   
524         /* OPX == mulxsu?  Then store. */         
525         xori r7, r4, 0x17                         
526         beq r7, zero, store_product               
527                                                   
528         /* Compute mulxss                         
529          *                                        
530          * mulxss = mulxsu - (rB < 0) ? rA : 0    
531          */                                       
532         bge r11,zero,mulxss_skip                  
533         sub r9, r9, r3                            
534 mulxss_skip:                                      
535         /* At this point, assume that OPX is m    
536                                                   
537                                                   
538 store_product:                                    
539         stw r9, 0(r6)                             
540                                                   
541                                                   
542 restore_registers:                                
543                         /* No need to restore     
544         ldw r5, 100(sp)                           
545         wrctl estatus, r5                         
546                                                   
547         ldw r1, 4(sp)                             
548         ldw r2, 8(sp)                             
549         ldw r3, 12(sp)                            
550         ldw r4, 16(sp)                            
551         ldw r5, 20(sp)                            
552         ldw r6, 24(sp)                            
553         ldw r7, 28(sp)                            
554         ldw r8, 32(sp)                            
555         ldw r9, 36(sp)                            
556         ldw r10, 40(sp)                           
557         ldw r11, 44(sp)                           
558         ldw r12, 48(sp)                           
559         ldw r13, 52(sp)                           
560         ldw r14, 56(sp)                           
561         ldw r15, 60(sp)                           
562         ldw r16, 64(sp)                           
563         ldw r17, 68(sp)                           
564         ldw r18, 72(sp)                           
565         ldw r19, 76(sp)                           
566         ldw r20, 80(sp)                           
567         ldw r21, 84(sp)                           
568         ldw r22, 88(sp)                           
569         ldw r23, 92(sp)                           
570                         /* Does not need to re    
571         ldw gp, 104(sp)                           
572                                                   
573         ldw fp, 112(sp)                           
574         ldw ea, 116(sp)                           
575         ldw ra, 120(sp)                           
576         ldw sp, 108(sp) /* last restore sp */     
577         eret                                      
578                                                   
579 .set at                                           
580 .set break                                        
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php