2 * linux/arch/nios2nommu/kernel/entry.S
4 * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
5 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
6 * Kenneth Albanowski <kjahds@kjahds.com>,
7 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
8 * Copyright (C) 2004 Microtronix Datacom Ltd.
12 * linux/arch/m68knommu/kernel/entry.S
14 * Copyright (C) 1991, 1992 Linus Torvalds
16 * This file is subject to the terms and conditions of the GNU General Public
17 * License. See the file README.legal in the main directory of this archive
20 * Linux/m68k support by Hamish Macdonald
22 * 68060 fixes by Jesper Skov
23 * ColdFire support by Greg Ungerer (gerg@snapgear.com)
24 * 5307 fixes by David W. Miller
25 * linux 2.4 support David McCullough <davidm@snapgear.com>
28 #include <linux/sys.h>
29 #include <linux/linkage.h>
30 #include <asm/asm-offsets.h>
31 #include <asm/asm-macros.h>
32 #include <asm/thread_info.h>
33 #include <asm/errno.h>
34 #include <asm/setup.h>
35 #include <asm/segment.h>
36 #include <asm/entry.h>
37 #include <asm/unistd.h>
38 #include <asm/traps.h>
39 #include <asm/processor.h>
47 rdctl r10,status /* enable intrs again */
52 stw r2,PT_R2(sp) /* default return value in r2 */
53 /* original r2 is in orig_r2 */
56 bgtu r3,r1,ret_from_exception
58 movhi r11,%hiadj(sys_call_table)
60 ldw r1,%lo(sys_call_table)(r1)
61 beq r1,r0,ret_from_exception
63 movi r11,%lo(0xffffe000) /* Get thread info pointer */
66 BTBNZ r11,r11,TIF_SYSCALL_TRACE_ASM,1f
69 stw r2,PT_R2(sp) /* save the return value */
75 /* wentao: restore r4-9, since they are trashed by syscall_trace */
83 stw r2,PT_R2(sp) /* save the return value */
89 ldw r1,PT_STATUS_EXTENSION(sp) /* check if returning to kernel */
90 TSTBZ r1,r1,PS_S_ASM,Luser_return /* if so, skip resched, signals */
93 rdctl r10,status /* disable intrs */
100 GET_THREAD_INFO r24 /* get thread_info pointer */
101 ldw r10,TI_FLAGS(r24) /* get thread_info->flags */
102 ANDI32 r11,r10,_TIF_WORK_MASK_ASM
103 beq r11,r0,restore_all /* Nothing to do */
104 BTBZ r1,r10,TIF_NEED_RESCHED_ASM,Lsignal_return
108 br ret_from_exception
111 BTBZ r1,r10,TIF_SIGPENDING_ASM,restore_all
112 mov r5,sp /* pt_regs */
114 CLR r4 /* oldset = 0 */
120 * Handle software exceptions. Put here so external interrupts
121 * can fall throught to ret_from_interrupt.
125 ldw r24,-4(ea) // instruction that caused the exception
126 xorhi r24,r24,0x003b // upper half of trap opcode
127 xori r24,r24,0x683a // lower half of trap opcode
128 bne r24,r0,instruction_trap /* N - check for instruction trap */
129 cmpeqi r11,r2,TRAP_ID_SYSCALL /* ? Is this a syscall */
130 bne r11,r0,system_call /* Y - handle syscall */
131 cmpeqi r11,r2,TRAP_ID_APPDEBUG /* ? Is this an application debug */
132 bne r11,r0,app_debug /* Y - handle app_debug */
133 cmpeqi r11,r2,63 /* ? Is this the old syscall number */
134 bne r11,r0,system_call /* Y - handle syscall to catch older apps*/
135 br restore_all /* N - everything else is ignored for now */
138 GET_THREAD_INFO r24 /* get thread_info */
139 ldw r1,TI_TASK(r24) /* get thread_info->task */
140 ldw r24,(TASK_THREAD + THREAD_FLAGS)(r1) /* get thread_info->task->thread.flags */
141 ORI32 r24, r24, NIOS2_FLAG_DEBUG /* set the debug flag */
142 stw r24,(TASK_THREAD + THREAD_FLAGS)(r1) /* save thread_info->task->thread.flags */
146 * This is the generic interrupt handler (for all hardware interrupt
147 * sources). It figures out the vector number and calls the appropriate
148 * interrupt service routine directly.
153 * Test to see if the exception was a software exception or caused by an
154 * external interrupt, and vector accordingly.
159 beq r24,r0,software_exception
161 beq r12,r0,software_exception
164 stw r24,PT_ORIG_R2(sp)
167 * Process an external hardware interrupt.
170 addi ea,ea,-4 /* re-issue the interrupted instruction */
172 rdctl r9,ienable /* Isolate possible interrupts */
174 beq r12,r0,ret_from_interrupt /* No one to service done */
175 movi r4,%lo(-1) /* Start from bit position 0, highest priority */
176 /* This is the IRQ # for handler call */
179 andi r10,r10,1 /* Isolate bit we are interested in */
180 cmpeqi r11,r4,32 /* ? End of the register */
181 bne r11,r0,ret_from_interrupt /* Y - out of here */
183 mov r5,sp /* Setup pt_regs pointer for handler call */
184 PUSH r4 /* Save state for return */
189 br 1b /* Check for other interrupts while here */
191 ENTRY(ret_from_interrupt)
192 ldw r4,PT_STATUS_EXTENSION(sp)
193 TSTBZ r4,r4,PS_S_ASM,Luser_return // Returning to user
195 #ifdef CONFIG_PREEMPT
197 ldw r4,TI_PREEMPT_COUNT(r1)
198 bne r4,r0,restore_all
201 ldw r4,TI_FLAGS(r1) // ? Need resched set
202 BTBZ r10,r4,TIF_NEED_RESCHED_ASM,restore_all
203 ldw r4,PT_ESTATUS(sp) // ? Interrupts off
204 BTBZ r10,r4,NIOS2_STATUS_PIE_OFST_ASM,restore_all
205 movia r4,PREEMPT_ACTIVE_ASM
206 stw r4,TI_PREEMPT_COUNT(r1)
207 rdctl r10,status /* enable intrs again */
214 stw r4,TI_PREEMPT_COUNT(r1)
215 rdctl r10,status /* disable intrs */
225 * Beware - when entering resume, prev (the current task) is
226 * in r4, next (the new task) is in r5, don't change these
231 rdctl r7,status /* save thread status reg */
232 stw r7,TASK_THREAD+THREAD_KPSR(r4)
234 andi r7,r7,0x0fffe /* disable interrupts */
237 movia r8,status_extension /* save status extension */
239 stw r7,TASK_THREAD+THREAD_KESR(r4)
242 stw sp,TASK_THREAD+THREAD_KSP(r4) /* save kernel stack pointer */
243 ldw sp,TASK_THREAD+THREAD_KSP(r5) /* restore new thread stack */
244 movia r24,_current_thread /* save thread */
249 ldw r7,TASK_THREAD+THREAD_KESR(r5) /* restore extended status reg */
252 ldw r7,TASK_THREAD+THREAD_KPSR(r5) /* restore thread status reg */
258 br ret_from_exception
288 ENTRY(sys_sigsuspend)
295 ENTRY(sys_rt_sigsuspend)
298 call do_rt_sigsuspend
309 ENTRY(sys_sigaltstack)
318 ENTRY(sys_rt_sigreturn)
324 /******************************************************************************
326 * License Agreement *
328 * Copyright (c) 2003 Altera Corporation, San Jose, California, USA. *
329 * All rights reserved. *
331 * Permission is hereby granted, free of charge, to any person obtaining a *
332 * copy of this software and associated documentation files (the "Software"), *
333 * to deal in the Software without restriction, including without limitation *
334 * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
335 * and/or sell copies of the Software, and to permit persons to whom the *
336 * Software is furnished to do so, subject to the following conditions: *
338 * The above copyright notice and this permission notice shall be included in *
339 * all copies or substantial portions of the Software. *
341 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
342 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
343 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
344 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
345 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
346 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
347 * DEALINGS IN THE SOFTWARE. *
349 * This agreement shall be governed in all respects by the laws of the State *
350 * of California and by the laws of the United States of America. *
352 ******************************************************************************/
355 * This is the software exception handler for Nios2.
359 * Explicitly allow the use of r1 (the assembler temporary register)
360 * within this code. This register is normally reserved for the use of
364 ENTRY(instruction_trap)
365 RESTORE_ALL // Clean off our save & setup for emulation
367 /* INSTRUCTION EMULATION
368 * ---------------------
370 * Nios II processors generate exceptions for unimplemented instructions.
371 * The routines below emulate these instructions. Depending on the
372 * processor core, the only instructions that might need to be emulated
373 * are div, divu, mul, muli, mulxss, mulxsu, and mulxuu.
375 * The emulations match the instructions, except for the following
378 * 1) The emulation routines do not emulate the use of the exception
379 * temporary register (et) as a source operand because the exception
380 * handler already has modified it.
382 * 2) The routines do not emulate the use of the stack pointer (sp) or the
383 * exception return address register (ea) as a destination because
384 * modifying these registers crashes the exception handler or the
385 * interrupted routine.
390 * The emulation routines expect the contents of integer registers r0-r31
391 * to be on the stack at addresses sp, 4(sp), 8(sp), ... 124(sp). The
392 * routines retrieve source operands from the stack and modify the
393 * destination register's value on the stack prior to the end of the
394 * exception handler. Then all registers except the destination register
395 * are restored to their previous values.
397 * The instruction that causes the exception is found at address -4(ea).
398 * The instruction's OP and OPX fields identify the operation to be
401 * One instruction, muli, is an I-type instruction that is identified by
402 * an OP field of 0x24.
404 * muli AAAAA,BBBBB,IIIIIIIIIIIIIIII,-0x24-
405 * 27 22 6 0 <-- LSB of field
407 * The remaining emulated instructions are R-type and have an OP field
408 * of 0x3a. Their OPX fields identify them.
410 * R-type AAAAA,BBBBB,CCCCC,XXXXXX,NNNNN,-0x3a-
411 * 27 22 17 11 6 0 <-- LSB of field
414 * Opcode Encoding. muli is identified by its OP value. Then OPX & 0x02
415 * is used to differentiate between the division opcodes and the remaining
416 * multiplication opcodes.
418 * Instruction OP OPX OPX & 0x02
419 * ----------- ---- ---- ----------
424 * mulxuu 0x3a 0x07 != 0
425 * mulxsu 0x3a 0x17 != 0
426 * mulxss 0x3a 0x1f != 0
431 * Save everything on the stack to make it easy for the emulation routines
432 * to retrieve the source register operands.
436 stw zero, 0(sp) // Save zero on stack to avoid special case for r0.
460 // Don't bother to save et. It's already been changed.
465 // Don't bother to save ea. It's already been changed.
471 * Split the instruction into its fields. We need 4*A, 4*B, and 4*C as
472 * offsets to the stack pointer for access to the stored register values.
474 ldw r2,-4(ea) // r2 = AAAAA,BBBBB,IIIIIIIIIIIIIIII,PPPPPP
475 roli r3,r2,7 // r3 = BBB,IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BB
476 roli r4,r3,3 // r4 = IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB
477 roli r5,r4,2 // r5 = IIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB,II
478 srai r4,r4,16 // r4 = (sign-extended) IMM16
479 roli r6,r5,5 // r6 = XXXX,NNNNN,PPPPPP,AAAAA,BBBBB,CCCCC,XX
480 andi r2,r2,0x3f // r2 = 00000000000000000000000000,PPPPPP
481 andi r3,r3,0x7c // r3 = 0000000000000000000000000,AAAAA,00
482 andi r5,r5,0x7c // r5 = 0000000000000000000000000,BBBBB,00
483 andi r6,r6,0x7c // r6 = 0000000000000000000000000,CCCCC,00
488 * r4 = IMM16 (sign extended)
497 * It is necessary to check for muli because it uses an I-type instruction
498 * format, while the other instructions are have an R-type format.
500 * Prepare for either multiplication or division loop.
501 * They both loop 32 times.
505 add r3,r3,sp // r3 = address of A-operand.
506 ldw r3,0(r3) // r3 = A-operand.
507 movi r7,0x24 // muli opcode (I-type instruction format)
508 beq r2,r7,mul_immed // muli doesn't use the B register as a source
510 add r5,r5,sp // r5 = address of B-operand.
511 ldw r5,0(r5) // r5 = B-operand.
512 // r4 = SSSSSSSSSSSSSSSS,-----IMM16------
513 // IMM16 not needed, align OPX portion
514 // r4 = SSSSSSSSSSSSSSSS,CCCCC,-OPX--,00000
515 srli r4,r4,5 // r4 = 00000,SSSSSSSSSSSSSSSS,CCCCC,-OPX--
516 andi r4,r4,0x3f // r4 = 00000000000000000000000000,-OPX--
522 * r4 = OPX (no longer can be muli)
529 * Multiply or Divide?
531 andi r7,r4,0x02 // For R-type multiply instructions, OPX & 0x02 != 0
537 * Divide an unsigned dividend by an unsigned divisor using
538 * a shift-and-subtract algorithm. The example below shows
539 * 43 div 7 = 6 for 8-bit integers. This classic algorithm uses a
540 * single register to store both the dividend and the quotient,
541 * allowing both values to be shifted with a single instruction.
543 * remainder dividend:quotient
544 * --------- -----------------
545 * initialize 00000000 00101011:
546 * shift 00000000 0101011:_
547 * remainder >= divisor? no 00000000 0101011:0
548 * shift 00000000 101011:0_
549 * remainder >= divisor? no 00000000 101011:00
550 * shift 00000001 01011:00_
551 * remainder >= divisor? no 00000001 01011:000
552 * shift 00000010 1011:000_
553 * remainder >= divisor? no 00000010 1011:0000
554 * shift 00000101 011:0000_
555 * remainder >= divisor? no 00000101 011:00000
556 * shift 00001010 11:00000_
557 * remainder >= divisor? yes 00001010 11:000001
558 * remainder -= divisor - 00000111
561 * shift 00000111 1:000001_
562 * remainder >= divisor? yes 00000111 1:0000011
563 * remainder -= divisor - 00000111
566 * shift 00000001 :0000011_
567 * remainder >= divisor? no 00000001 :00000110
569 * The quotient is 00000110.
574 * Prepare for division by assuming the result
575 * is unsigned, and storing its "sign" as 0.
580 // Which division opcode?
581 xori r7,r4,0x25 // OPX of div
582 bne r7,zero,unsigned_division
586 * OPX is div. Determine and store the sign of the quotient.
587 * Then take the absolute value of both operands.
589 xor r17,r3,r5 // MSB contains sign of quotient
590 bge r3,zero,dividend_is_nonnegative
591 sub r3,zero,r3 // -r3
592 dividend_is_nonnegative:
593 bge r5,zero,divisor_is_nonnegative
594 sub r5,zero,r5 // -r5
595 divisor_is_nonnegative:
599 // Initialize the unsigned-division loop.
600 movi r13,0 // remainder = 0
603 * r3 = dividend : quotient
604 * r4 = 0x25 for div, 0x24 for divu
607 * r14 = loop counter (already initialized to 32)
608 * r17 = MSB contains sign of quotient
613 * for (count = 32; count > 0; --count)
621 * (remainder:dividend:quotient) <<= 1;
624 cmplt r7,r3,zero // r7 = MSB of r3
630 * if (remainder >= divisor)
632 * set LSB of quotient
633 * remainder -= divisor;
645 bne r14,zero,divide_loop
650 * r4 = 0x25 for div, 0x24 for divu
652 * r17 = MSB contains sign of quotient
657 * Conditionally negate signed quotient. If quotient is unsigned,
658 * the sign already is initialized to 0.
660 bge r17,zero,quotient_is_nonnegative
661 sub r3,zero,r3 // -r3
662 quotient_is_nonnegative:
666 * Final quotient is in r3.
669 stw r3,0(r6) // write quotient to stack
677 * A "product" is the number that one gets by summing a "multiplicand"
678 * several times. The "multiplier" specifies the number of copies of the
679 * multiplicand that are summed.
681 * Actual multiplication algorithms don't use repeated addition, however.
682 * Shift-and-add algorithms get the same answer as repeated addition, and
683 * they are faster. To compute the lower half of a product (pppp below)
684 * one shifts the product left before adding in each of the partial products
685 * (a * mmmm) through (d * mmmm).
687 * To compute the upper half of a product (PPPP below), one adds in the
688 * partial products (d * mmmm) through (a * mmmm), each time following the
689 * add by a right shift of the product.
701 * The example above shows 4 partial products. Computing actual Nios II
702 * products requires 32 partials.
704 * It is possible to compute the result of mulxsu from the result of mulxuu
705 * because the only difference between the results of these two opcodes is
706 * the value of the partial product associated with the sign bit of rA.
708 * mulxsu = mulxuu - (rA < 0) ? rB : 0;
710 * It is possible to compute the result of mulxss from the result of mulxsu
711 * because the only difference between the results of these two opcodes is
712 * the value of the partial product associated with the sign bit of rB.
714 * mulxss = mulxsu - (rB < 0) ? rA : 0;
719 // Opcode is muli. Change it into mul for remainder of algorithm.
720 mov r6,r5 // Field B is dest register, not field C.
721 mov r5,r4 // Field IMM16 is src2, not field B.
722 movi r4,0x27 // OPX of mul is 0x27
725 // Initialize the multiplication loop.
726 movi r9,0 // mul_product = 0
727 movi r10,0 // mulxuu_product = 0
728 mov r11,r5 // save original multiplier for mulxsu and mulxss
729 mov r12,r5 // mulxuu_multiplier (will be shifted)
730 movi r16,1 // used to create "rori B,A,1" from "ror B,A,r16"
734 * r5 = mul_multiplier
735 * r6 = 4 * dest_register (used later as offset to sp)
738 * r10 = mulxuu_product
739 * r11 = original multiplier
740 * r12 = mulxuu_multiplier
741 * r14 = loop counter (already initialized)
747 * for (count = 32; count > 0; --count)
754 * lsb = multiplier & 1;
762 * mulxuu_product += multiplicand;
765 beq r7,zero,mulx_skip
767 cmpltu r7,r10,r3 // Save the carry from the MSB of mulxuu_product.
768 ror r7,r7,r16 // r7 = 0x80000000 on carry, or else 0x00000000
772 * if (MSB of mul_multiplier == 1)
774 * mul_product += multiplicand;
782 * mulxuu_product >>= 1; logical shift
783 * mul_multiplier <<= 1; done with MSB
784 * mulx_multiplier >>= 1; done with LSB
787 or r10,r10,r7 // OR in the saved carry bit.
796 bne r14,zero,multiply_loop
800 * Multiply emulation loop done.
806 * r6 = 4 * dest_register (used later as offset to sp)
809 * r10 = mulxuu_product
810 * r11 = original multiplier
814 // Calculate address for result from 4 * dest_register
819 * Select/compute the result based on OPX.
823 // OPX == mul? Then store.
825 beq r7,zero,store_product
827 // It's one of the mulx.. opcodes. Move over the result.
830 // OPX == mulxuu? Then store.
832 beq r7,zero,store_product
836 // mulxsu = mulxuu - (rA < 0) ? rB : 0;
838 bge r3,zero,mulxsu_skip
842 // OPX == mulxsu? Then store.
844 beq r7,zero,store_product
848 // mulxss = mulxsu - (rB < 0) ? rA : 0;
850 bge r11,zero,mulxss_skip
853 // At this point, assume that OPX is mulxss, so store
861 // No need to restore r0.