This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: SH1 port of eCos



Yes, this is exactly what I was thinking when I mentioned saving a little
bit of state then jumping to the main interrupt handler.  There is a
problem with the current organization of the SH saved registers if I want
to do this.  The general purpose regs are the last things saved on entry to
an interrupt.  If I change the order, I could reduce the amount of code in
each instantiation of the "INTERRUPT" macro.

On the SH1, an interrupt entry would look something like (this is
completely off the top of my head):

.macro INTERRUPT
	// SR and PC already saved on the stack
	.org	vectors + (12*VECTOR)
	add     #-4, r15	// save a spot for r15(SP)
	mov.l   r14,@-r15	// save a scratch register
	bra	interrupt
	mov	$vec_ ## VECTOR,r14	// store vector for exception handler
	$vec_ ## VECTOR:	// how do you concatenate?
		.long exception_table + (VECTOR << 2)
  	.set VECTOR, VECTOR+1
.endm

FUNC_START(interrupt)
	mov.l   r13,@-r15	// save rest of regs
	// ...
	mov.l   r0,@-r15
	sts.l   pr,@-r15
	sts.l   mach,@-r15
	sts.l   macl,@-r15
	// fixup saved stack pointer here
	// do all the rest of the interrupt code here

	mov.l	$restore_state, r0
	lds	r0,pr
	jmp	r14	// jump to C exception handler
	nop
$restore_state:
	.long restore_state


The stack frame would now look like:
cyg_uint32   mach;                  // Multiply and accumulate - high
cyg_uint32   macl;                  // Multiply and accumulate - low
cyg_uint32   pr;                    // Procedure Reg
cyg_uint32   r[16];                 // Data regs
cyg_uint32   pc;                    // Program Counter
cyg_uint32   sr;                    // Status Reg

And each "INTERRUPT" entry is 12 bytes.  If instead, I did the easy save
everything macro that jumps directly to the C ISR, I'd probably use maybe
100 or so bytes for each and they'd end up a slight bit faster.

All of this, unfortunately, is much messier than what is currently there
for the SH3.  I don't see any way to do this nicely.

Aaron


> Aaron Passey wrote:
> > You have one nice interrupt routine and another exception routine.  I need
> > potentially 256 copies of this routine.  I could do this with a bunch of
> > macros and a lot of code duplication (not pretty) or possibly have a macro
> > that saves a little bit of state, calls another routine to save the rest,
> > and then jumps to the right ISR.  I have to think about this a little bit
> > more.
> 
> I don't know the details here, but I think certain GAS constructs may be
> useful in this, e.g. paraphrased from the v850 vectors.S
> 
> 	.macro INTERRUPT
>         .org    reset_vector+(0x0010*VECTOR)
>         addi    -CYGARC_EXCEPTION_FRAME_SIZE,sp,sp
>         st.w    r1,CYGARC_REG_R1[sp]
>         movea   VECTOR,r0,r1
>         jr      exception
>  	.set VECTOR, VECTOR+1
> 	.endm
> 
> and then later:
> 
> 	.set VECTOR, 8
> 	.rept CYGNUM_HAL_ISR_COUNT
> 	INTERRUPT
> 	.endr
> 
> Do you see what this does and how it does it? A small preamble that
> identifies the vector in a register, followed by a jump. And all contained
> in a macro in a way that is clean, even though CYGNUM_HAL_ISR_COUNT is very
> large on the v850, like the SH1.
> 
> Jifl
> -- 
> Red Hat, Rustat House, Clifton Road, Cambridge, UK. Tel: +44 (1223) 271062
> Un cheval, pas du glue. Pas du cheval, beaucoup du glue. || Opinions==mine

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]