|
@@ -0,0 +1,419 @@
|
|
|
+{
|
|
|
+ This file is part of the Free Pascal run time library.
|
|
|
+ Copyright (c) 2006-2007 by David Zhang
|
|
|
+
|
|
|
+ Processor dependent implementation for the system unit for MIPS
|
|
|
+
|
|
|
+ See the file COPYING.FPC, included in this distribution,
|
|
|
+ for details about the copyright.
|
|
|
+
|
|
|
+ This program is distributed in the hope that it will be useful,
|
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
+
|
|
|
+ **********************************************************************}
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ MIPS specific stuff
|
|
|
+****************************************************************************}
|
|
|
+function get_fsr : dword;assembler;nostackframe;[public, alias: 'FPC_GETFSR'];
|
|
|
+ var
|
|
|
+ fsr : dword;
|
|
|
+ asm
|
|
|
+ cfc1 $2,$31
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+procedure set_fsr(fsr : dword);assembler;[public, alias: 'FPC_SETFSR'];
|
|
|
+ var
|
|
|
+ _fsr : dword;
|
|
|
+ asm
|
|
|
+ ctc1 $4,$31
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+function get_got_z : pointer;assembler;nostackframe;[public, alias: 'FPC_GETGOT_Z'];
|
|
|
+ asm
|
|
|
+ move $2,$28
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+procedure fpc_cpuinit;
|
|
|
+var
|
|
|
+ tmp32: longint;
|
|
|
+ begin
|
|
|
+ { enable div by 0 and invalid operation fpu exceptions }
|
|
|
+ { round towards zero; ieee compliant arithmetics }
|
|
|
+
|
|
|
+ tmp32 := get_fsr();
|
|
|
+ set_fsr((tmp32 and $fffffffc) or $00000001);
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+{$define FPC_SYSTEM_HAS_GET_FRAME}
|
|
|
+function get_frame:pointer;assembler;nostackframe;
|
|
|
+ asm
|
|
|
+ lw $2,0($sp)
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
|
|
|
+function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
|
|
|
+ asm
|
|
|
+ lw $2,4($4) #movl 4(%eax),%eax
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
|
|
|
+function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
|
|
|
+ asm
|
|
|
+ lw $2,0($4)#movl (%eax),%eax
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+{$define FPC_SYSTEM_HAS_SPTR}
|
|
|
+function Sptr:Pointer;assembler;nostackframe;
|
|
|
+ asm
|
|
|
+ move $2,$sp
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+{$ifndef FPC_SYSTEM_HAS_MOVE}
|
|
|
+{$define FPC_SYSTEM_HAS_MOVE}
|
|
|
+procedure Move(const source;var dest;count:longint);[public, alias: 'FPC_MOVE'];assembler;
|
|
|
+ asm
|
|
|
+{
|
|
|
+ Registers:
|
|
|
+ $7 temp. to do copying
|
|
|
+ $8 inc/decrement
|
|
|
+ $9/l0/l1/l2 qword move
|
|
|
+}
|
|
|
+
|
|
|
+ sw $4,0($23)
|
|
|
+ sw $5,-4($23)
|
|
|
+ sw $6,-8($23)
|
|
|
+ sw $7,-12($23)
|
|
|
+ sw $8,-16($23)
|
|
|
+ sw $9,-20($23)
|
|
|
+ sw $10,-24($23)
|
|
|
+ sw $11,-28($23)
|
|
|
+ sw $12,-32($23)
|
|
|
+ sw $13,-36($23)
|
|
|
+ sw $14,-40($23)
|
|
|
+ addiu $23,$23,-44
|
|
|
+
|
|
|
+
|
|
|
+ # count <= 0 ?
|
|
|
+ ble $6,$0,.Lmoveexit
|
|
|
+ nop
|
|
|
+
|
|
|
+ # source = dest ?
|
|
|
+ beq $4,$5,.Lmoveexit
|
|
|
+ nop
|
|
|
+
|
|
|
+ # possible overlap?
|
|
|
+ bgt $4,$5,.Lnopossibleoverlap
|
|
|
+ nop
|
|
|
+ # source < dest ....
|
|
|
+ addu $7,$6,$4
|
|
|
+ # overlap?
|
|
|
+ # source+count < dest ?
|
|
|
+ blt $7,$5,.Lnopossibleoverlap
|
|
|
+ nop
|
|
|
+
|
|
|
+ .Lcopybackward:
|
|
|
+ # check alignment of source and dest
|
|
|
+ or $2,$4,$5
|
|
|
+
|
|
|
+ # move src and dest to the end of the blocks
|
|
|
+ # assuming 16 byte block size
|
|
|
+ addiu $3,$6,-1
|
|
|
+ addu $4,$4,$3
|
|
|
+ addu $5,$5,$3
|
|
|
+
|
|
|
+ b .Lmovebytewise
|
|
|
+ li $3,-1
|
|
|
+
|
|
|
+.Lnopossibleoverlap:
|
|
|
+
|
|
|
+ # check alignment of source and dest
|
|
|
+ or $2,$4,$5
|
|
|
+
|
|
|
+ # everything 16 byte aligned ?
|
|
|
+ andi $13,$2,15
|
|
|
+
|
|
|
+ beq $13,$0,.Lmovetwordwise
|
|
|
+ # load direction in delay slot
|
|
|
+ li $3,16
|
|
|
+
|
|
|
+
|
|
|
+ andi $13,$2,7
|
|
|
+ beq $13,$0,.Lmoveqwordwise
|
|
|
+ li $3,8
|
|
|
+
|
|
|
+ andi $13,$2,3
|
|
|
+ beq $13,$0,.Lmovedwordwise
|
|
|
+ li $3,4
|
|
|
+
|
|
|
+ andi $13,$2,1
|
|
|
+ beq $13,$0,.Lmovewordwise
|
|
|
+ li $3,2
|
|
|
+ b .Lmovebytewise
|
|
|
+ li $3,1
|
|
|
+
|
|
|
+.Lmovetwordwise:
|
|
|
+ srl $13,$6,4
|
|
|
+ sll $14,$13,4
|
|
|
+ beq $14,$0,.Lmoveqwordwise_shift
|
|
|
+ nop
|
|
|
+
|
|
|
+.Lmovetwordwise_loop:
|
|
|
+ lw $9,0($4)
|
|
|
+ lw $10,4($4)
|
|
|
+ addiu $13,$13,-1
|
|
|
+ lw $11,8($4)
|
|
|
+ lw $12,12($4)
|
|
|
+ addu $4,$4,$3
|
|
|
+ sw $9,0($5)
|
|
|
+ sw $10,4($5)
|
|
|
+ sw $11,8($5)
|
|
|
+ sw $12,12($5)
|
|
|
+ addu $5,$5,$3
|
|
|
+ bne $13,$0,.Lmovetwordwise_loop
|
|
|
+ nop
|
|
|
+ subu $6,$6,$14
|
|
|
+ beq $6,$0,.Lmoveexit
|
|
|
+ nop
|
|
|
+
|
|
|
+.Lmoveqwordwise_shift:
|
|
|
+ sra $3,$3,1
|
|
|
+
|
|
|
+.Lmoveqwordwise:
|
|
|
+ srl $13,$6,3
|
|
|
+ sll $14,$13,3
|
|
|
+ beq $14,$0,.Lmovedwordwise_shift
|
|
|
+ nop
|
|
|
+
|
|
|
+ .Lmoveqwordwise_loop:
|
|
|
+ lw $9,0($4)
|
|
|
+ lw $10,4($4)
|
|
|
+ addiu $13,$13,-1
|
|
|
+ addu $4,$3,$4
|
|
|
+ sw $9,0($5)
|
|
|
+ sw $10,4($5)
|
|
|
+ addu $5,$3,$5
|
|
|
+ bne $13,0,.Lmoveqwordwise_loop
|
|
|
+ nop
|
|
|
+
|
|
|
+ subu $6,$6,$14
|
|
|
+ beq $6,$0,.Lmoveexit
|
|
|
+ nop
|
|
|
+
|
|
|
+ .Lmovedwordwise_shift:
|
|
|
+ sra $3,$3,1
|
|
|
+
|
|
|
+ .Lmovedwordwise:
|
|
|
+ srl $13,$6,2
|
|
|
+ sll $14,$13,2
|
|
|
+ beq $14,$0,.Lmovewordwise_shift
|
|
|
+ nop
|
|
|
+
|
|
|
+ .Lmovedwordwise_loop:
|
|
|
+ lw $9,0($4)
|
|
|
+ addiu $13,$13,-1
|
|
|
+ addu $4,$4,$3
|
|
|
+ sw $9,0($5)
|
|
|
+ addu $5,$5,$3
|
|
|
+ bne $13,$0,.Lmovedwordwise_loop
|
|
|
+ nop
|
|
|
+
|
|
|
+ subu $6,$6,$14
|
|
|
+ beq $6,$0,.Lmoveexit
|
|
|
+ nop
|
|
|
+
|
|
|
+ .Lmovewordwise_shift:
|
|
|
+ sra $3,$3,1
|
|
|
+ .Lmovewordwise:
|
|
|
+ srl $13,$6,1
|
|
|
+ sll $14,$13,1
|
|
|
+ beq $14,$0, .Lmovebytewise_shift
|
|
|
+ nop
|
|
|
+
|
|
|
+ .Lmovewordwise_loop:
|
|
|
+ lhu $9,0($4)
|
|
|
+ addiu $13,$13,-1
|
|
|
+ addu $4,$4,$3
|
|
|
+ sh $9,0($5)
|
|
|
+ addu $5,$5,$3
|
|
|
+ bne $13,$0,.Lmovewordwise_loop
|
|
|
+ nop
|
|
|
+
|
|
|
+ subu $6,$6,$14
|
|
|
+ beq $6,$0, .Lmoveexit
|
|
|
+ nop
|
|
|
+
|
|
|
+ .Lmovebytewise_shift:
|
|
|
+ sra $3,$3,1
|
|
|
+ .Lmovebytewise:
|
|
|
+ beq $6,$0, .Lmoveexit
|
|
|
+ nop
|
|
|
+
|
|
|
+ lbu $9,0($4)
|
|
|
+ addiu $6,$6,-1
|
|
|
+ addu $4,$4,$3
|
|
|
+ sb $9,0($5)
|
|
|
+ addu $5,$5,$3
|
|
|
+ bne $6,$0,.Lmovebytewise
|
|
|
+ nop
|
|
|
+ .Lmoveexit:
|
|
|
+
|
|
|
+ addiu $23,$23,44
|
|
|
+ lw $4,0($23)
|
|
|
+ lw $5,-4($23)
|
|
|
+ lw $6,-8($23)
|
|
|
+ lw $7,-12($23)
|
|
|
+ lw $8,-16($23)
|
|
|
+ lw $9,-20($23)
|
|
|
+ lw $10,-24($23)
|
|
|
+ lw $11,-28($23)
|
|
|
+ lw $12,-32($23)
|
|
|
+ lw $13,-36($23)
|
|
|
+ lw $14,-40($23)
|
|
|
+
|
|
|
+ end;
|
|
|
+{$endif FPC_SYSTEM_HAS_MOVE}
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ Integer math
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+{$define FPC_SYSTEM_HAS_ABS_LONGINT}
|
|
|
+function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}nostackframe;{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_abs];{$endif}
|
|
|
+asm
|
|
|
+ sra $1,$4,31 #$at,$4,31
|
|
|
+ xor $2,$4,$1 #$2,$4,$at
|
|
|
+ sub $2,$2,$1 #$2,$2,$at
|
|
|
+end;
|
|
|
+
|
|
|
+var
|
|
|
+ fpc_system_lock : longint; export name 'fpc_system_lock';
|
|
|
+
|
|
|
+
|
|
|
+{$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
|
|
|
+function declocked(var l : longint) : boolean;assembler;nostackframe;
|
|
|
+{ input: address of l in $4 }
|
|
|
+{ output: boolean indicating whether l is zero after decrementing }
|
|
|
+asm
|
|
|
+ sw $4,0($23)
|
|
|
+ sw $5,-4($23)
|
|
|
+ sw $6,-8($23)
|
|
|
+ sw $7,-12($23)
|
|
|
+ sw $8,-16($23)
|
|
|
+ sw $9,-20($23)
|
|
|
+ sw $10,-24($23)
|
|
|
+ sw $11,-28($23)
|
|
|
+ sw $12,-32($23)
|
|
|
+ sw $13,-36($23)
|
|
|
+ sw $14,-40($23)
|
|
|
+ addiu $23,$23,-44
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+.Ldeclocked1:
|
|
|
+ lui $5,%hi(fpc_system_lock)
|
|
|
+ addiu $5,$5,%lo(fpc_system_lock)
|
|
|
+ ll $6,0($5)
|
|
|
+ ori $7,$6,1
|
|
|
+ beq $7,$6,.Ldeclocked1
|
|
|
+ nop
|
|
|
+ sc $7,0($5)
|
|
|
+
|
|
|
+ beq $7,$0,.Ldeclocked1
|
|
|
+ nop
|
|
|
+
|
|
|
+ lw $5,0($4)
|
|
|
+ addiu $5,$5,-1
|
|
|
+ sw $5,0($4)
|
|
|
+ seq $2,$5,$0
|
|
|
+
|
|
|
+
|
|
|
+ { unlock }
|
|
|
+ lui $5,%hi(fpc_system_lock)
|
|
|
+ addiu $5,$5,%lo(fpc_system_lock)
|
|
|
+ sw $0,0($5)
|
|
|
+
|
|
|
+ addiu $23,$23,44
|
|
|
+ lw $4,0($23)
|
|
|
+ lw $5,-4($23)
|
|
|
+ lw $6,-8($23)
|
|
|
+ lw $7,-12($23)
|
|
|
+ lw $8,-16($23)
|
|
|
+ lw $9,-20($23)
|
|
|
+ lw $10,-24($23)
|
|
|
+ lw $11,-28($23)
|
|
|
+ lw $12,-32($23)
|
|
|
+ lw $13,-36($23)
|
|
|
+ lw $14,-40($23)
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+{$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
|
|
|
+procedure inclocked(var l : longint);assembler;nostackframe;
|
|
|
+asm
|
|
|
+ { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
|
|
|
+ worse the effort, especially while waiting :)
|
|
|
+ }
|
|
|
+
|
|
|
+ { unlock }
|
|
|
+
|
|
|
+ sw $4,0($23)
|
|
|
+ sw $5,-4($23)
|
|
|
+ sw $6,-8($23)
|
|
|
+ sw $7,-12($23)
|
|
|
+ sw $8,-16($23)
|
|
|
+ sw $9,-20($23)
|
|
|
+ sw $10,-24($23)
|
|
|
+ sw $11,-28($23)
|
|
|
+ sw $12,-32($23)
|
|
|
+ sw $13,-36($23)
|
|
|
+ sw $14,-40($23)
|
|
|
+ addiu $23,$23,-44
|
|
|
+
|
|
|
+
|
|
|
+.Ldeclocked1:
|
|
|
+ lui $5,%hi(fpc_system_lock)
|
|
|
+ addiu $5,$5,%lo(fpc_system_lock)
|
|
|
+ ll $6,0($5)
|
|
|
+ ori $7,$6,1
|
|
|
+ beq $7,$6,.Ldeclocked1
|
|
|
+ nop
|
|
|
+ sc $7,0($5)
|
|
|
+
|
|
|
+ beq $7,$0,.Ldeclocked1
|
|
|
+ nop
|
|
|
+
|
|
|
+ lw $5,0($4)
|
|
|
+ addiu $5,$5,1
|
|
|
+ sw $5,0($4)
|
|
|
+
|
|
|
+
|
|
|
+ { unlock }
|
|
|
+ lui $5,%hi(fpc_system_lock)
|
|
|
+ addiu $5,$5,%lo(fpc_system_lock)
|
|
|
+ sw $0,0($5)
|
|
|
+
|
|
|
+ addiu $23,$23,44
|
|
|
+ lw $4,0($23)
|
|
|
+ lw $5,-4($23)
|
|
|
+ lw $6,-8($23)
|
|
|
+ lw $7,-12($23)
|
|
|
+ lw $8,-16($23)
|
|
|
+ lw $9,-20($23)
|
|
|
+ lw $10,-24($23)
|
|
|
+ lw $11,-28($23)
|
|
|
+ lw $12,-32($23)
|
|
|
+ lw $13,-36($23)
|
|
|
+ lw $14,-40($23)
|
|
|
+
|
|
|
+end;
|