Ruth Hendrix

Adding a value to the Program Counter

Discussion created by Ruth Hendrix Employee on Jan 24, 2006
This message contains an entire topic ported from a separate forum. The original message and all replies are in this single message. We have seeded this new forum with selected information that we expect will be of value to you as you search for answers to your questions.
 
Posted: Fri Aug 19, 2005 3:48 am    
 
Hi,

We are translating some PIC assembly code to 08. We need to add a value in the low nybble after a mask operation to the PC. The resultant value will then increment the PC to the correct location. Here is an example...

lda DATA
and #$0F ;and with mask to enable low nibble
add PCL ;add resultant value to low byte of program counter

The PC would immediatly go to one of the branch locations below.

bra ERROR_1
bra ERROR_2
bra ERROR_3
bra ERROR_4
bra ERROR_5
bra ERROR_6

This routine is very timing critical so I cannot use a CBEQA to compare a incrementing value as the execution time would vary. Any suggestions?

Posted: Fri Aug 19, 2005 8:06 am    
 
Hi,

why don´t you use an indexed jump ?.
This is a clean solution and has one extra cycle in the worst case.

Posted: Fri Aug 19, 2005 9:15 am    
 
Hi

first i tought on a routin to calculate the new PC with some stack an HX calculating. But Eckhard is rigth here the code (i tested it with the EBS08_RC8 template):


Code:
PC_TEST: LDA #1 ;for test only STA TMPA ;your variable DATA! INDEX_JUMP: LDHX #ERROR_1X ;Error table in HX STHX POINTER ;for calculating LDA TMPA ;your variable DATA AND #$0F SUB #1 ;for offsetError_1 is 0! LSLA ;Offset *2 ADD POINTER+1 ;calculate the new PC value STA POINTER+1 LDA POINTER ADC #0 STA POINTER LDHX POINTER ;Adress in HX JMP ,X ;JUMP to the adress ERROR_1X: ;Error routine table BRA ERROR_1 ERROR_2X: BRA ERROR_2 ERROR_3X: BRA ERROR_3 ERROR_4X: BRA ERROR_4 ERROR_5X: BRA ERROR_5 ERROR_6X: BRA ERROR_6 ERROR_7X: BRA ERROR_7 ERROR_8X: BRA ERROR_8 ERROR_1: JMP PC_TESTE ERROR_2: JMP PC_TESTE ERROR_3: JMP PC_TESTE ERROR_4: JMP PC_TESTE ERROR_5: JMP PC_TESTE ERROR_6: JMP PC_TESTE ERROR_7: JMP PC_TESTE ERROR_8: PC_TESTE:

 
Posted: Sun Aug 21, 2005 10:59 am    

Hi

I have been thinking about solutions for the problem!

Here some of them:

First try how Paul51 askd for:

Erste Lösung mit berechnen des neuen Programm-Counters:

This solution changes the PC; with the RTS command the programm continues
with the new PC value.

Is uses 57 cycles to preform the operation!

Code:

**** PCTEST PC_TEST: LDA #1 ;for test only STA TMPA ;your variable DATA! * Start JSR PC_CHANGE PC_CHANGE: LDHX #ERROR_1X ;Error table in HX STHX POINTER ;for calculating LDA TMPA ;your variable DATA AND #$0F SUB #1 ;for offsetError_1 is 0! LSLA ;Offset *2 ADD POINTER+1 ;calculate the new PC value STA POINTER+1 LDA POINTER ADC #0 STA POINTER LDHX POINTER PULA ;to move the stack pointer to PULA ;the right position PSHX ;to put the new PC value onto the stack PSHH RTS ;now we jump to the right address!!!! ERROR_1X: ;Error routine table BRA ERROR_1 ERROR_2X: BRA ERROR_2 ERROR_3X: BRA ERROR_3 ERROR_4X: BRA ERROR_4 ERROR_5X: BRA ERROR_5 ERROR_6X: BRA ERROR_6 ERROR_7X: BRA ERROR_7 ERROR_8X: BRA ERROR_8 ERROR_1: JMP PC_TESTE ERROR_2: JMP PC_TESTE ERROR_3: JMP PC_TESTE ERROR_4: JMP PC_TESTE ERROR_5: JMP PC_TESTE ERROR_6: JMP PC_TESTE ERROR_7: JMP PC_TESTE ERROR_8: PC_TESTE: 


 Second solution after the tip

2. Lösung mit indiziertem Sprung und 16bit Berechnung:

A fast shot (modifing the first solution)

It uses 43 cycles (14 less than the first sulution)


Code:

**** PCTEST PC_TEST: LDA #1 ;for test only STA TMPA ;your variable DATA! * Start INDEX_JUMP: LDHX #ERROR_1X ;Error table in HX STHX POINTER ;for calculating LDA TMPA ;your variable DATA AND #$0F SUB #1 ;for offsetError_1 is 0! LSLA ;Offset *2 ADD POINTER+1 ;calculate the new PC value STA POINTER+1 LDA POINTER ADC #0 STA POINTER LDHX POINTER ;Adress in HX JMP ,X ;JUMP to the adress ERROR_1X: ;Error routine table BRA ERROR_1 ERROR_2X: BRA ERROR_2 ERROR_3X: BRA ERROR_3 ERROR_4X: BRA ERROR_4 ERROR_5X: BRA ERROR_5 ERROR_6X: BRA ERROR_6 ERROR_7X: BRA ERROR_7 ERROR_8X: BRA ERROR_8 ERROR_1: JMP PC_TESTE ERROR_2: JMP PC_TESTE ERROR_3: JMP PC_TESTE ERROR_4: JMP PC_TESTE ERROR_5: JMP PC_TESTE ERROR_6: JMP PC_TESTE ERROR_7: JMP PC_TESTE ERROR_8: PC_TESTE: 


 Ok but we can make it faster by using only a 8 bit value so here
the third try:

It uses 20 cycles (much faster)

Code:

PC_TEST: LDA #1 ;for test only STA TMPA ;your variable DATA! * Start INDEX_JUMP: LDHX #0 ;Clear HX LDA TMPA ;your variable DATA AND #$0F SUB #1 ;for offsetError_1 is 0! LSLA ;Offset *2 TAX ;Accu -> X (offset to ERROR_1X) ; JMP ERROR_1X,X ;JUMP to the adress ERROR_1X + offset ERROR_1X: ;Error routine table BRA ERROR_1 ERROR_2X: BRA ERROR_2 ERROR_3X: BRA ERROR_3 ERROR_4X: BRA ERROR_4 ERROR_5X: BRA ERROR_5 ERROR_6X: BRA ERROR_6 ERROR_7X: BRA ERROR_7 ERROR_8X: BRA ERROR_8 ERROR_1: JMP PC_TESTE ERROR_2: JMP PC_TESTE ERROR_3: JMP PC_TESTE ERROR_4: JMP PC_TESTE ERROR_5: JMP PC_TESTE ERROR_6: JMP PC_TESTE ERROR_7: JMP PC_TESTE ERROR_8: PC_TESTE: 


 To save more cycles we can eliminate the SUB #1 (DECA would be also a solution but)
when change the offset to ERROR_1X-2 we can save 2 cycles

This solution uses 18 cycles now!

Code:

PC_TEST: LDA #1 ;for test only STA TMPA ;your variable DATA! * Start INDEX_JUMP: LDHX #0 ;Clear HX LDA TMPA ;your variable DATA AND #$0F LSLA ;Offset *2 TAX ;Accu -> X (offset to ERROR_1X) ; JMP ERROR_1X-2,X ;JUMP to the adress ERROR_1X - 2 + offset ERROR_1X: ;Error routine table BRA ERROR_1 ERROR_2X: BRA ERROR_2 ERROR_3X: BRA ERROR_3 ERROR_4X: BRA ERROR_4 ERROR_5X: BRA ERROR_5 ERROR_6X: BRA ERROR_6 ERROR_7X: BRA ERROR_7 ERROR_8X: BRA ERROR_8 ERROR_1: JMP PC_TESTE ERROR_2: JMP PC_TESTE ERROR_3: JMP PC_TESTE ERROR_4: JMP PC_TESTE ERROR_5: JMP PC_TESTE ERROR_6: JMP PC_TESTE ERROR_7: JMP PC_TESTE ERROR_8: PC_TESTE: 


 A othe way to do it with a table. Unfortunatly we can not
load the HX register indexed with X so we have to load the POINTER variable!

it uses 32 cycles an jumps directly to the desired address!

Code:

PC_TEST: LDA #1 ;for test only STA TMPA ;your variable DATA! * Start INDEX_JUMP: LDHX #0 ;Clear HX LDA TMPA ;your variable DATA AND #$0F LSLA ;Offset *2 TAX ;Accu -> X (offset to ERROR_1X) LDA ERROR_1X-2,X ;Load the Pointer with the STA POINTER ;desired error address LDA ERROR_1X-1,X STA POINTER+1 LDHX POINTER ;Pointer to HX JMP ,X ;and Jump to the address ERROR_1X: DC.W ERROR_1 ;Error routine table ERROR_2X: DC.W ERROR_2 ERROR_3X: DC.W ERROR_3 ERROR_4X: DC.W ERROR_4 ERROR_5X: DC.W ERROR_5 ERROR_6X: DC.W ERROR_6 ERROR_7X: DC.W ERROR_7 ERROR_8X: DC.W ERROR_8 ERROR_1: JMP PC_TESTE ERROR_2: JMP PC_TESTE ERROR_3: JMP PC_TESTE ERROR_4: JMP PC_TESTE ERROR_5: JMP PC_TESTE ERROR_6: JMP PC_TESTE ERROR_7: JMP PC_TESTE ERROR_8: PC_TESTE: 


 I hope that helps

Saluti

Posted: Thu Dec 15, 2005 9:05 pm    

Hi,

Can some one give me an example of an indexed jump? This seems to be the best solution but I have only used the X register in the past with 05 parts. Do not know how to use the HX register.

Thanks to everyone for all of your help.

Posted: Fri Dec 16, 2005 1:50 am    

G'day,

 

Quote:
Can some one give me an example of an indexed jump? This seems to be the best solution but I have only used the X register in the past with 05 parts. Do not know how to use the HX register.



Here is a simple example of an indexed jump that will work with both 05 and 08 parts (in the latter case, the H register needs to be set to zero). It is assumed that the DATA register would contain the value 0, 1, ... etc. There is no protection against going beyond the end of the table.

 

 

Code:

LDX  DATA LSLX          ; Since BRA instruction uses 2 bytes CLRH JMP  TABLE,X TABLE: BRA  ERROR_1 BRA  ERROR_2 etc. 


 



'TABLE' can be located anywhere in memory, but needs to be within relative jump range of 'ERROR_1', etc. If you needed to do other things following the execution of one of the error routines, you could substitute JSR TABLE,X for the JMP instruction.

I hope this clarifies the situation.

Regards,

Outcomes