diff --git a/compiler/avr/ccpuinnr.inc b/compiler/avr/ccpuinnr.inc index bf365e2232..9ab4f327a3 100644 --- a/compiler/avr/ccpuinnr.inc +++ b/compiler/avr/ccpuinnr.inc @@ -16,4 +16,6 @@ in_avr_sei = fpc_in_cpu_first+1, in_avr_wdr = fpc_in_cpu_first+2, in_avr_sleep = fpc_in_cpu_first+3, - in_avr_nop = fpc_in_cpu_first+4 + in_avr_nop = fpc_in_cpu_first+4, + in_avr_save = fpc_in_cpu_first+5, + in_avr_restore = fpc_in_cpu_first+6 diff --git a/compiler/avr/navrinl.pas b/compiler/avr/navrinl.pas index f7577eea7b..4b8662f502 100644 --- a/compiler/avr/navrinl.pas +++ b/compiler/avr/navrinl.pas @@ -42,7 +42,9 @@ unit navrinl; aasmdata, aasmcpu, symdef, - cgbase, + hlcgobj, + pass_2, + cgbase, cgobj, cgutils, cpubase; function tavrinlinenode.pass_typecheck_cpu : tnode; @@ -58,6 +60,16 @@ unit navrinl; CheckParameters(0); resultdef:=voidtype; end; + in_avr_save: + begin + CheckParameters(0); + resultdef:=u8inttype; + end; + in_avr_restore: + begin + CheckParameters(1); + resultdef:=voidtype; + end; else Result:=inherited pass_typecheck_cpu; end; @@ -72,11 +84,17 @@ unit navrinl; in_avr_sleep, in_avr_sei, in_avr_wdr, - in_avr_cli: + in_avr_cli, + in_avr_restore: begin expectloc:=LOC_VOID; resultdef:=voidtype; end; + in_avr_save: + begin + expectloc:=LOC_REGISTER; + resultdef:=u8inttype; + end; else Result:=inherited first_cpu; end; @@ -96,6 +114,20 @@ unit navrinl; current_asmdata.CurrAsmList.concat(taicpu.op_none(A_WDR)); in_avr_cli: current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLI)); + in_avr_save: + begin + location_reset(location,LOC_CREGISTER,OS_8); + location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_8); + + current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_IN, location.register, NIO_SREG)); + current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLI)); + end; + in_avr_restore: + begin + secondpass(left); + hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); + current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_OUT, NIO_SREG, left.location.register)); + end; else inherited pass_generate_code_cpu; end; diff --git a/compiler/pdecsub.pas b/compiler/pdecsub.pas index 9632a4afa1..fe0906a156 100644 --- a/compiler/pdecsub.pas +++ b/compiler/pdecsub.pas @@ -2542,7 +2542,7 @@ const mutexclpo : [] ),( idtok:_INTERNPROC; - pd_flags : [pd_interface,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper]; + pd_flags : [pd_interface,pd_implemen,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper]; handler : @pd_internproc; pocall : pocall_internproc; pooption : []; diff --git a/rtl/avr/avr.inc b/rtl/avr/avr.inc index 4844844672..933c54c76e 100644 --- a/rtl/avr/avr.inc +++ b/rtl/avr/avr.inc @@ -17,6 +17,15 @@ {$asmmode gas} +const +{$i cpuinnr.inc} + +{ Reads SREG and then disables interrupts, returns contents of SREG } +function avr_save: byte;[INTERNPROC: in_avr_save]; +{ Restores SREG } +procedure avr_restore(old_sreg: byte); [INTERNPROC: in_avr_restore]; + + procedure fpc_cpuinit;{$ifdef SYSTEMINLINE}inline;{$endif} begin end; @@ -84,19 +93,19 @@ function get_frame:pointer;assembler;nostackframe; {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR} -function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler; +function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe; asm end; {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME} -function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler; +function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe; asm end; {$define FPC_SYSTEM_HAS_SPTR} -Function Sptr : pointer;assembler; +Function Sptr : pointer;assembler;nostackframe; asm end; @@ -106,20 +115,13 @@ function InterLockedDecrement (var Target: longint) : longint; temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); - dec(Target); - Result:=Target; + Result:=Target-1; + Target:=Result; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -128,20 +130,13 @@ function InterLockedIncrement (var Target: longint) : longint; temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); - inc(Target); - Result:=Target; + Result:=Target+1; + Target:=Result; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -150,20 +145,13 @@ function InterLockedExchange (var Target: longint;Source : longint) : longint; temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); Result:=Target; Target:=Source; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -172,21 +160,14 @@ function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comp temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); Result:=Target; - if Target=Comperand then + if Result=Comperand then Target:=NewValue; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -195,20 +176,13 @@ function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); Result:=Target; - inc(Target,Source); + Target:=Result+Source; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -217,20 +191,13 @@ function InterLockedDecrement (var Target: smallint) : smallint; temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); - dec(Target); - Result:=Target; + Result:=Target-1; + Target:=Result; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -239,20 +206,13 @@ function InterLockedIncrement (var Target: smallint) : smallint; temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); - inc(Target); - Result:=Target; + Result:=Target+1; + Target:=Result; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -261,20 +221,13 @@ function InterLockedExchange (var Target: smallint;Source : smallint) : smallint temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); Result:=Target; Target:=Source; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -283,21 +236,14 @@ function InterlockedCompareExchange(var Target: smallint; NewValue: smallint; Co temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); Result:=Target; - if Target=Comperand then + if Result=Comperand then Target:=NewValue; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; @@ -306,19 +252,12 @@ function InterLockedExchangeAdd (var Target: smallint;Source : smallint) : small temp_sreg : byte; begin { block interrupts } - asm - in r0,0x3f - std temp_sreg,r0 - cli - end; + temp_sreg:=avr_save(); Result:=Target; - inc(Target,Source); + Target:=Result+Source; { release interrupts } - asm - ldd r0,temp_sreg - out 0x3f,r0 - end; + avr_restore(temp_sreg); end; diff --git a/rtl/avr/cpuinnr.inc b/rtl/avr/cpuinnr.inc index 02adeaf48d..3ffcb009cb 100644 --- a/rtl/avr/cpuinnr.inc +++ b/rtl/avr/cpuinnr.inc @@ -17,3 +17,5 @@ in_avr_wdr = fpc_in_cpu_first+2; in_avr_sleep = fpc_in_cpu_first+3; in_avr_nop = fpc_in_cpu_first+4; + in_avr_save = fpc_in_cpu_first+5; + in_avr_restore = fpc_in_cpu_first+6; diff --git a/rtl/avr/intrinsics.pp b/rtl/avr/intrinsics.pp index ee498e51ef..c640acb318 100644 --- a/rtl/avr/intrinsics.pp +++ b/rtl/avr/intrinsics.pp @@ -24,6 +24,11 @@ unit intrinsics; procedure avr_sleep;[INTERNPROC: in_avr_sleep]; procedure avr_nop;[INTERNPROC: in_avr_nop]; + { Reads SREG and then disables interrupts, returns contents of SREG } + function avr_save: byte;[INTERNPROC: in_avr_save]; + { Restores SREG } + procedure avr_restore(old_sreg: byte); [INTERNPROC: in_avr_restore]; + implementation end.