From: George M. G. <gga...@co...> - 2005-01-11 14:00:44
|
I am looking for a syntax to use for calling into a OS. There is a dispatch table, at a known address, of service functions such as putc that I have been using from assembler. Currently I create an assembler program that just jumps to the service as in: org 0x200 _putc: goto PUTC _getc: goto GETC It would be desirable to use and include file or be able to import symbol definitions into the linker. Thanks, George |
From: Vangelis R. <vr...@ot...> - 2005-01-12 17:38:44
|
----- Original Message -----=20 From: "George M. Gallant" <gga...@co...> To: <sdc...@li...> Subject: [Sdcc-user] Calling semi known routines Hello George, >I am looking for a syntax to use for calling into a OS. There is a=20 > dispatch table, at a known address, > of service functions such as putc that I have been using from = assembler.=20 > Currently I create an assembler > program that just jumps to the service as in: >=20 > org 0x200 >=20 > _putc: goto PUTC > _getc: goto GETC >=20 > It would be desirable to use and include file or be able to import=20 > symbol definitions into the linker. Wouldn't an 'extern' declaration work for you? What calling convention are you using for these functions? Is it = standard SDCC/pic16 calling conventions? If yes, you can prototype them in a header file, and just call them from source. (I assume you have a RET instruction somewhere right?) regards, Vangelis |
From: panocomp <pan...@gm...> - 2005-01-13 07:56:26
|
>Hello George, > > > >>I am looking for a syntax to use for calling into a OS. There is a >>dispatch table, at a known address, >>of service functions such as putc that I have been using from assembler. >>Currently I create an assembler >>program that just jumps to the service as in: >> >> org 0x200 >> >> _putc: goto PUTC >> _getc: goto GETC >> >>It would be desirable to use and include file or be able to import >>symbol definitions into the linker. >> >> > >Wouldn't an 'extern' declaration work for you? > >What calling convention are you using for these functions? Is it standard >SDCC/pic16 calling conventions? If yes, you can prototype them in >a header file, and just call them from source. (I assume you have a RET >instruction somewhere right?) > >regards, >Vangelis > > > Hello, here a classic methode for calling OS routines. If I remember Minix from Tannenbaum do the same way. First declare a function table p.e.with enumerations for your functions. In application call at function like _putc. In this routine build stack entries according to the rules used by hardware interrupts. Put the enumerated function number into a register not used for function parameters by the compiler. The return address on the stack must be your jump table switch routine inside your OS. Then leave your _putc user function with inline assembler reti instruction (hardware interrupt return). The manipulated stack will be cleared. Code jump to your OS switch function, there jump to your OS inside linked function. The stack is like in your user programm so you can leave the OS function normal way with ret and usual return values. The trick of prepearing stack and using reti for function calls make the linking of your application independent from OS as long you dot't make any changes of the address of switch table in your OS. It will be necessary that function parameters are passed by registers or on the stack. Regards Wolfgang Rapp |
From: Vangelis R. <vr...@ot...> - 2005-01-13 09:37:58
|
----- Original Message -----=20 From: "panocomp" <pan...@gm...> To: <sdc...@li...> Subject: Re: [Sdcc-user] Calling semi known routines It is possible in PIC18Fs to do a 'come-from' jump! One can: 1. push on the stack the return address 2. push on the stack the target address 3. execute a return address from caller I think I could make pic16 port to jump to a specific function's entry point using the above scheme. It can be done with pragma directives. > here a classic methode for calling OS routines. If I remember Minix = from=20 > Tannenbaum do the same way. > First declare a function table p.e.with enumerations for your = functions. > In application call at function like _putc. In this routine build = stack=20 > entries according to the rules used by hardware interrupts. > Put the enumerated function number into a register not used for = function=20 > parameters by the compiler. > The return address on the stack must be your jump table switch routine = > inside your OS. > Then leave your _putc user function with inline assembler reti=20 > instruction (hardware interrupt return). The manipulated stack will be = > cleared. > Code jump to your OS switch function, there jump to your OS inside=20 > linked function. The stack is like in your user programm > so you can leave the OS function normal way with ret and usual return=20 > values. >=20 > The trick of prepearing stack and using reti for function calls make = the=20 > linking of your application independent from OS as long > you dot't make any changes of the address of switch table in your OS. > It will be necessary that function parameters are passed by registers = or=20 > on the stack. |
From: Thorsten K. <Tho...@gm...> - 2005-01-14 00:33:05
|
Hi, apropos support for operating systems: some time ago I wrote a C wrapper for MIOS (an assembler project which is also hosted at sourceforge) which worked well until one of the last changes in the PIC16 module. Since some days the first function parameter won't be forwarded via WREG, but will be pushed on the stack like the other parameters. Therefore the wrapper is not working anymore. An adaption to the new compiler behaviour would lead to a significant higher code memory usage within the wrapper and to performance loss. However, I'm wondering if this is the final parameter handling so that it makes sense that I start with a new wrapper, or (and I must admit that I would love this even more) if an optional switch for the old handling is feasible? Best Regards, Thorsten. |
From: Daniel W. <mai...@da...> - 2005-01-14 07:55:24
|
Hi, [...] > Since some days the first function parameter won't be forwarded via WREG, > but will be pushed on the stack like the other parameters. [...] > However, I'm wondering if this is the final parameter handling so that > it makes sense that I start with a new wrapper, or (and I must admit that > I would love this even more) if an optional switch for the old handling > is feasible? With parameters passed via WREG, calls via function pointers were a problem, so the default behaviour was changed. If you want the old style back, add #pragma wparam foo, bar, ... to tell SDCC, that the functions foo and bar should get their last byte via WREG. Keep in mind, that you must not call these functions over function pointers! HTH Daniel |
From: Thorsten K. <Tho...@gm...> - 2005-01-14 19:23:10
|
Hi Daniel, On Friday 14 January 2005 08:55, Daniel Winkler wrote: > With parameters passed via WREG, calls via function pointers were a > problem, so the default behaviour was changed. I just have checked the code which is generated on an indirect call: ------------------------------------------------------------ PUSH MOVLW LOW(_00111_DS_) MOVWF TOSL MOVLW HIGH(_00111_DS_) MOVWF TOSH MOVLW UPPER(_00111_DS_) MOVWF TOSU MOVFF r0x02, PCLATU MOVFF r0x01, PCLATH MOVF r0x00, W MOVWF PCL _00111_DS_: ------------------------------------------------------------ perhaps following code helps to use WREG again? ------------------------------------------------------------ rcall _TMP_LABEL1 bra _TMP_LABEL2 _TMP_LABEL1 push movf r0x00, W movwf TOSL movf r0x01, W movwf TOSH movf r0x02, W movwf TOSU return _TMP_LABEL2 ------------------------------------------------------------ this would: a) save one instruction b) allow you to load something into WREG before the return c) help to reduce the code size in general due to the simplified parameter passing method > If you want the old style back, add > #pragma wparam foo, bar, ... > to tell SDCC, that the functions foo and bar should get their last byte > via WREG. Keep in mind, that you must not call these functions over > function pointers! thank you, this pragma saved my day! :) Best Regards, Thorsten. |
From: Vangelis R. <vr...@ot...> - 2005-01-14 23:36:55
|
----- Original Message -----=20 From: "Thorsten Klose" <Tho...@gm...> To: <sdc...@li...> Subject: Re: [Sdcc-user] Calling semi known routines >> With parameters passed via WREG, calls via function pointers were a >> problem, so the default behaviour was changed. >=20 > I just have checked the code which is generated on an indirect call: >=20 > ------------------------------------------------------------ > PUSH =20 > MOVLW LOW(_00111_DS_) > MOVWF TOSL > MOVLW HIGH(_00111_DS_) > MOVWF TOSH > MOVLW UPPER(_00111_DS_) > MOVWF TOSU > MOVFF r0x02, PCLATU > MOVFF r0x01, PCLATH > MOVF r0x00, W > MOVWF PCL > _00111_DS_: > ------------------------------------------------------------ >=20 >=20 > perhaps following code helps to use WREG again? >=20 > ------------------------------------------------------------ > rcall _TMP_LABEL1 > bra _TMP_LABEL2 > _TMP_LABEL1 > push > movf r0x00, W > movwf TOSL > movf r0x01, W > movwf TOSH > movf r0x02, W > movwf TOSU > return > _TMP_LABEL2 > ------------------------------------------------------------ >=20 > this would: > a) save one instruction But uses one more slot in the hardware stack. Its 32 levels deep, but still useful! > b) allow you to load something into WREG before the return I knew that it would be possible to implement something like this. I skipped this section because I had to focus on something else... I'll try to implement your approach, too. Thanks. >> If you want the old style back, add >> #pragma wparam foo, bar, ... >> to tell SDCC, that the functions foo and bar should get their last = byte >> via WREG. Keep in mind, that you must not call these functions over >> function pointers! >=20 > thank you, this pragma saved my day! :) Thank you too, Daniel!:-) I was preparing a command line option to globally enable WPARAM for all functions, but I realized that this is not possible since all libraries should be compiled with this option, and all project modules should also be compiled with this option. So I think we should stick to the pragma approach. regards, Vangelis |