123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 1993,97 by Carl-Eric Codere,
- member of the Free Pascal development team.
- 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.
- **********************************************************************}
- {****************************************************************************
- m68k.inc : Processor dependent implementation of system unit
- For Motorola 680x0 Processor.
-
- *****************************************************************************}
- {****************************************************************************}
- { This include file contains as little assembler as possible, to make }
- { porting to other systems easier. }
- { Port to the Motorola 680x0 compiler by: }
- { }
- { Carl-Eric Codere - port of non-system specific stuff. }
- { }
- { Some routines taken from the Atari freeware dlib source code, created by: }
- { Dale Schumacher 399 Beacon Ave. }
- { (alias: Dalnefre') St. Paul, MN 55104 }
- { [email protected] United States of America }
- { Some routines taken from the freeware Atari Sozobon C compiler, created by:}
- { 1988 by Sozobon, Limited. Author: Johann Ruegg (freeware) }
- { Thanks to all these people wherever they maybe today! }
- { BUGS in sqr and abs for return values. Only longint seems supported. }
- { }
- { Still left to do: }
- { mod_rr routine to convert to pascal format. }
- { }
- { ALL routines in set.inc, system.inc and real2str.inc are system independant.}
- {****************************************************************************}
- { Don't call the following routines directly. }
- Procedure Hlt;[public,alias: 'HALT_ERROR'];
- { called by code generator on run-time errors. }
- { on entry contains d0 = error code. }
- var
- b:byte; { only byte is used... }
- begin
- asm
- move.b d0,b
- end;
- RunError(b);
- end;
- Procedure FillChar(var x; count: longint; value: byte);[alias: 'L_FILL_OBJECT'];
- begin
- asm
- move.l 8(a6), a0 { destination }
- move.l 12(a6), d1 { number of bytes to fill }
- move.b 16(a6),d0 { fill data }
- cmpi.l #65535, d1 { check, if this is a word move }
- ble @LMEMSET3 { use fast dbra mode }
- bra @LMEMSET2
- @LMEMSET1:
- move.b d0,(a0)+
- @LMEMSET2:
- subq.l #1,d1
- cmp.b #-1,d1
- bne @LMEMSET1
- bra @LMEMSET5 { finished slow mode , exit }
- @LMEMSET4: { fast loop mode section 68010+ }
- move.b d0,(a0)+
- @LMEMSET3:
- dbra d1,@LMEMSET4
- @LMEMSET5:
- end ['d0','d1','a0'];
- end;
- Procedure FillObject(var x; count: longint; value: byte);
- begin
- asm
- move.l 8(a6), a0 { destination }
- move.l 12(a6), d1 { number of bytes to fill }
- move.w 16(a6),d0 { fill data }
- cmp.l #65535, d1 { check, if this is a word move }
- ble @LMEMSET3 { use fast dbra mode }
- bra @LMEMSET2
- @LMEMSET1:
- move.b d0,(a0)+
- @LMEMSET2:
- subq.l #1,d1
- cmp.b #-1,d1
- bne @LMEMSET1
- bra @LMEMSET5 { finished slow mode , exit }
- @LMEMSET4: { fast loop mode section 68010+ }
- move.b d0,(a0)+
- @LMEMSET3:
- dbra d1,@LMEMSET4
- @LMEMSET5:
- end ['d0','d1','a0'];
- end;
- procedure int_help_constructor;
- begin
- asm
- XDEF HELP_CONSTRUCTOR
- { Entry without preamble, since we need the ESP of the
- constructor }
- { Stack (relative to %ebp):
- 12 Self
- 8 VMT-Address
- 4 main programm-Addr
- 0 %ebp
- }
- { do we have to initialize self }
- { we just need to check for zero }
- move.l a5,d0
- tst.l d0 { set flags }
- bne @LHC_4
- { get memory, but save register first }
- { temporary variable }
- subq.l #4,sp
- move.l sp,a5
- { Save Registers }
- movem.l d0-a7,-(sp)
- { Memory size }
- move.l 8(a6),a0
- move.l (a0),-(sp)
- { push method pointer }
- move.l a5,-(sp)
- jsr GETMEM
- { Restore all registers in the correct order }
- movem.l (sp)+,d0-a7
- { Memory size to a5 }
- move.l (a5),a5
- add.l #4,sp
- { If no memory available : fail() }
- move.l a5,d0
- tst.l d0 { set flags for a5 }
- beq @LHC_5
- { init self for the constructor }
- move.l a5,12(a6)
- @LHC_4:
- { is there a VMT address ? }
- move.l 8(a6),d0
- or.l d0,d0
- bne @LHC_7
- { In case the constructor doesn't do anything, the Zero-Flag }
- { can't be put, because this calls Fail() }
- add.l #1,d0
- rts
- @LHC_7:
- { set zero inside the object }
- { Save Registers }
- movem.l d0-a7,-(sp)
- move.w #0,-(sp)
- move.l 8(a6),a0
- move.l (a0),-(sp)
- move.l a5,-(sp)
- { }
- jsr FILLOBJECT
- { Restore all registers in the correct order }
- movem.l (sp)+,d0-a7
- { set the VMT address for the new created object }
- move.l 8(a6),d0
- move.l d0,(a5)
- or.l d0,d0
- @LHC_5:
- rts
- end;
- end;
- procedure help_fail;
- begin
- asm
- end;
- end;
- procedure int_help_destructor;
- begin
- asm
- { Stack (relative to %ebp):
- 12 Self
- 8 VMT-Address
- 4 Main program-Addr
- 0 %ebp
- }
- { temporary Variable }
- XDEF HELP_DESTRUCTOR
- subq.l #4,sp
- move.l sp,d6
- { Save Registers }
- movem.l d0-a7,-(sp)
- move.l 8(a6),d0 { Get the address of the vmt }
- or.l d0,d0 { Check if there is a vmt }
- beq @LHD_3
- { Yes, get size from SELF! }
- move.l 12(a6),a0
- { get VMT-pointer (from Self) to %ebx }
- move.l (a0),a1
- { And put size on the Stack }
- move.l (a1),-(sp)
- { SELF }
- { I think for precaution }
- { that we should clear the VMT here }
- clr.l (a0)
- { get address of local variable into }
- { address register }
- move.l d6,a1
- move.l a0,(a1)
- move.l a1,-(sp)
- jsr FREEMEM
- @LHD_3:
- { Restore all registers in the correct order }
- movem.l (sp)+,d0-a7
- add.l #4,sp
- rts
- end;
- end;
- procedure new_class;assembler;
- asm
- XDEF NEW_CLASS
- { create class ? }
- move.l 8(a6), d0
- tst.l d0
- { check for nil... }
- beq @NEW_CLASS1
- { a5 contains vmt }
- move.l a5,-(sp)
- { call newinstance (class method!) }
- jsr 16(a5)
- { new instance returns a pointer to the new created }
- { instance in d0 }
- { load a5 and insert self }
- move.l d0,8(a6)
- move.l d0,a5
- bra @end
- @NEW_CLASS1:
- move.l a5,8(a6)
- @end:
- end;
- procedure dispose_class;assembler;
- asm
- XDEF DISPOSE_CLASS
- { destroy class ? }
- move.l 8(a6),d0
- { save self }
- move.l a5,8(a6)
- tst.l d0
- beq @DISPOSE_CLASS
- { no inherited call }
- move.l (a5),d0
- { push self }
- move.l a5,-(sp)
- { call freeinstance }
- move.l d0,a0
- jsr 20(a0)
- @DISPOSE_CLASS:
- { load self }
- move.l 8(a6),a5
- end;
- { checks for a correct vmt pointer }
- procedure co;assembler;
- { ON ENTRY: a0 -> Pointer to the VMT }
- { Nota: All registers must be preserved including }
- { A0 itself! }
- asm
- XDEF CHECK_OBJECT
- move.l d0,-(sp)
- tst.l a0
- { z flag set if zero }
- beq @co_re
- move.l (a0),d0
- add.l 4(a0),d0
- bne @co_re
- bra @end
- @co_re:
- move.l (sp)+,d0
- move.b #210,d0
- jsr HALT_ERROR
- @end:
- move.l (sp)+,d0
- end;
- function get_addr(BP : longint) : longint;
- begin
- asm
- move.l BP,a0
- cmp.l #0,a0
- beq @Lnul_address
- move.l 4(a0),a0
- @Lnul_address:
- move.l a0,@RESULT
- end ['a0'];
- end;
- function get_next_frame(bp : longint) : longint;
- begin
- asm
- move.l bp,a0
- cmp.l #0,a0
- beq @Lnul_frame
- move.l (a0),a0
- @Lnul_frame:
- move.l a0,@RESULT
- end ['a0'];
- end;
- procedure runerror(w : word);
- function get_addr : longint;
- begin
- asm
- move.l (a6),a0
- move.l 4(a0),a0
- move.l a0,@RESULT
- end ['a0'];
- end;
- function get_error_bp : longint;
- begin
- asm
- { get base pointer of error }
- move.l (a6),d0
- move.l d0,@RESULT
- end ['d0'];
- end;
- begin
- errorcode:=w;
- exitcode:=w;
- erroraddr:=pointer(get_addr);
- DoError:=True;
- ErrorBase:=get_error_bp;
- halt(byte(errorcode));
- end;
- procedure io1(addr : longint);[public,alias: 'IOCHECK'];
- var
- l : longint;
- begin
- { Since IOCHECK is called directly and only later the optimiser }
- { Maybe also save global registers }
- asm
- movem.l d0-a7,-(sp)
- end;
- l:=ioresult;
- if l<>0 then
- begin
- writeln('IO-Error ',l,' at 0x',HexStr(addr,8));
- halt(byte(l));
- end;
- asm
- { the register are put back in the correct order }
- movem.l (sp)+,d0-a7
- end;
- end;
- procedure re_overflow;[public,alias: 'RE_OVERFLOW'];
- var
- addr : longint;
- begin
- { Overflow was shortly before the return address }
- asm
- move.l 4(a6),d0
- move.l d0,addr
- end;
- writeln('Overflow at 0x',HexStr(addr,8));
- RunError(215);
- end;
- { procedure strcopy(dstr,sstr : pointer;len : longint);[public,alias: 'STRCOPY'];}
- procedure strcopy; assembler;
- {---------------------------------------------------}
- { Low-level routine to copy a string to another }
- { string with maximum length. Never call directly! }
- { On Entry: }
- { a1.l = string to copy to }
- { a0.l = source string }
- { d0.l = maximum length of copy }
- { registers destroyed: a0,a1,d0,d1 }
- {---------------------------------------------------}
- asm
- XDEF STRCOPY
- { move.l 12(a6),a0
- move.l 16(a6),a1
- move.l 8(a6),d1 }
- move.l d0,d1
- move.b (a0)+,d0 { Get source length }
- and.w #$ff,d0
- cmp.w d1,d0 { This is a signed comparison! }
- ble @LM4
- move.b d1,d0 { If longer than maximum size of target, cut
- source length }
- @LM4:
- andi.l #$ff,d0 { zero extend d0-byte }
- move.l d0,d1 { save length to copy }
- move.b d0,(a1)+ { save new length }
- { Check if copying length is zero - if so then }
- { exit without copying anything. }
- tst.b d1
- beq @Lend
- bra @LMSTRCOPY55
- @LMSTRCOPY56: { 68010 Fast loop mode }
- move.b (a0)+,(a1)+
- @LMSTRCOPY55:
- dbra d1,@LMSTRCOPY56
- @Lend:
- end;
- { Concatenate Strings }
- { PARAMETERS ARE REVERSED COMPARED TO NORMAL! }
- { therefore online assembler may not parse the params as normal }
- procedure strconcat(s1,s2 : pointer);[public,alias: 'STRCONCAT'];
- begin
- asm
- move.b #255,d0
- move.l s1,a0 { a0 = destination }
- move.l s2,a1 { a1 = source }
- sub.b (a0),d0 { copyl:= 255 -length(s1) }
- move.b (a1),d6
- and.w #$ff,d0 { Sign flags are checked! }
- and.w #$ff,d6
- cmp.w d6,d0 { if copyl > length(s2) then }
- ble @Lcontinue
- move.b (a1),d0 { copyl:=length(s2) }
- @Lcontinue:
- move.b (a0),d6
- and.l #$ff,d6
- lea 1(a0,d6),a0 { s1[length(s1)+1] }
- add.l #1,a1 { s2[1] }
- move.b d0,d6
- { Check if copying length is zero - if so then }
- { exit without copying anything. }
- tst.b d6
- beq @Lend
- bra @ALoop
- @Loop:
- move.b (a1)+,(a0)+ { s1[i] := s2[i]; }
- @ALoop:
- dbra d6,@Loop
- move.l s1,a0
- add.b d0,(a0) { change to new string length }
- @Lend:
- end ['d0','d1','a0','a1','d6'];
- end;
- { Compares strings }
- { DO NOT CALL directly. }
- { a0 = pointer to first string to compare }
- { a1 = pointer to second string to compare }
- { ALL FLAGS are set appropriately. }
- { ZF = strings are equal }
- { REGISTERS DESTROYED: a0, a1, d0, d1, d6 }
- procedure strcmp; assembler;
- asm
- XDEF STRCMP
- move.b (a0)+,d0 { Get length of first string }
- move.b (a1)+,d6 { Get length of 2nd string }
- move.b d6,d1 { Save length of string for final compare }
- cmp.b d0,d6 { Get shortest string length }
- ble @LSTRCONCAT1
- move.b d0,d6 { Set length to shortest string }
- @LSTRCONCAT1:
- tst.b d6 { Both strings have a length of zero, exit }
- beq @LSTRCONCAT2
- andi.l #$ff,d6
- subq.l #1,d6 { subtract first attempt }
- { if value is -1 then don't loop and just compare lengths of }
- { both strings before exiting. }
- bmi @LSTRCONCAT2
- or.l d0,d0 { Make sure to set Zerfo flag to 0 }
- @LSTRCONCAT5:
- { Workaroung for GAS v.134 bug }
- { old: cmp.b (a1)+,(a0)+ }
- cmpm.b (a1)+,(a0)+
- @LSTRCONCAT4:
- dbne d6,@LSTRCONCAT5 { Repeat until not equal }
- bne @LSTRCONCAT3
- @LSTRCONCAT2:
- { If length of both string are equal }
- { Then set zero flag }
- cmp.b d1,d0 { Compare length - set flag if equal length strings }
- @LSTRCONCAT3:
- end;
- Function strpas(p: pchar): string;
- { only 255 first characters are actually copied. }
- var
- counter : byte;
- str: string;
- Begin
- counter := 0;
- str := '';
- while (ord(p[counter]) <> 0) and (counter < 255) do
- begin
- counter:=counter+1;
- str[counter] := char(p[counter-1]);
- end;
- str[0] := char(counter);
- strpas := str;
- end;
- function strlen(p : pchar) : longint;
- var
- counter : longint;
- Begin
- counter := 0;
- repeat
- counter:=counter+1;
- until ord(p[counter]) = 0;
- strlen := counter;
- end;
- procedure move(var source;var dest;count : longint);
- { base pointer+8 = source }
- { base pointer+12 = destination }
- { base pointer+16 = number of bytes to move}
- begin
- asm
- clr.l d0
- move.l 16(a6),d0 { number of bytes }
- @LMOVE0:
- move.l 12(a6),a1 { destination }
- move.l 8(a6),a0 { source }
- cmpi.l #65535, d0 { check, if this is a word move }
- ble @LMEMSET00 { use fast dbra mode 68010+ }
- cmp.l a0,a1 { check copy direction }
- bls @LMOVE4
- add.l d0,a0 { move pointers to end }
- add.l d0,a1
- bra @LMOVE2
- @LMOVE1:
- move.b -(a0),-(a1) { (s < d) copy loop }
- @LMOVE2:
- subq.l #1,d0
- cmpi.l #-1,d0
- bne @LMOVE1
- bra @LMOVE5
- @LMOVE3:
- move.b (a0)+,(a1)+ { (s >= d) copy loop }
- @LMOVE4:
- subq.l #1,d0
- cmpi.l #-1,d0
- bne @LMOVE3
- bra @LMOVE5
- @LMEMSET00: { use fast loop mode 68010+ }
- cmp.l a0,a1 { check copy direction }
- bls @LMOVE04
- add.l d0,a0 { move pointers to end }
- add.l d0,a1
- bra @LMOVE02
- @LMOVE01:
- move.b -(a0),-(a1) { (s < d) copy loop }
- @LMOVE02:
- dbra d0,@LMOVE01
- bra @LMOVE5
- @LMOVE03:
- move.b (a0)+,(a1)+ { (s >= d) copy loop }
- @LMOVE04:
- dbra d0,@LMOVE03
- { end fast loop mode }
- @LMOVE5:
- end ['d0','a0','a1'];
- end;
- procedure fillword(var x;count : longint;value : word);
- begin
- asm
- move.l 8(a6), a0 { destination }
- move.l 12(a6), d1 { number of bytes to fill }
- move.w 16(a6),d0 { fill data }
- bra @LMEMSET21
- @LMEMSET11:
- move.w d0,(a0)+
- @LMEMSET21:
- subq.l #1,d1
- cmp.b #-1,d1
- bne @LMEMSET11
- end ['d0','d1','a0'];
- end;
- function abs(l : longint) : longint;
- begin
- asm
- move.l 8(a6),d0
- tst.l d0
- bpl @LMABS1
- neg.l d0
- @LMABS1:
- move.l d0,@RESULT
- end ['d0'];
- end;
- function odd(l : longint) : boolean;
- begin
- if (l and $01) = $01 then
- odd := TRUE
- else
- odd := FALSE;
- end;
- function sqr(l : longint) : longint;
- begin
- sqr := l*l;
- end;
- procedure int_str(l : longint;var s : string);
- var
- value: longint;
- negative: boolean;
- begin
- negative := false;
- s:='';
- { Workaround: }
- if l=$80000000 then
- begin
- s:='-2147483648';
- exit;
- end;
- { handle case where l = 0 }
- if l = 0 then
- begin
- s:='0';
- exit;
- end;
- If l < 0 then
- begin
- negative := true;
- value:=abs(l);
- end
- else
- value:=l;
- { handle non-zero case }
- while value>0 do
- begin
- s:=char((value mod 10)+ord('0'))+s;
- value := value div 10;
- end;
- if negative then
- s := '-' + s;
- end;
- procedure f1;[public,alias: 'FLUSH_STDOUT'];
- begin
- asm
- { Save Registers }
- movem.l d0-a7,-(sp)
- end;
- FileFunc(textrec(output).flushfunc)(textrec(output));
- asm
- { Restore all registers in the correct order }
- movem.l (sp)+,d0-a7
- end;
- end;
- Function Sptr : Longint;
- begin
- asm
- move.l sp,d0
- add.l #8,d0
- move.l d0,@RESULT
- end ['d0'];
- end;
- Procedure BoundsCheck;assembler;
- { called by code generator with R+ state to }
- { determine if a range check occured. }
- { Only in 68000 mode, in 68020 mode this is }
- { inline. }
- { On Entry: }
- { A1 = address contaning min and max indexes }
- { D0 = value of current index to check. }
- asm
- XDEF RE_BOUNDS_CHECK
- cmp.l (A1),D0 { lower bound ... }
- bmi @rebounderr { is index lower ... }
- add.l #4,A1
- cmp.l (A1),D0
- bmi @reboundend
- beq @reboundend
- @rebounderr:
- move.l #201,d0
- jsr HALT_ERROR
- @reboundend:
- end;
- {
- $Log$
- Revision 1.7 1998-07-02 12:20:58 carl
- + Io-Error and overflow print erroraddr in hex now
- Revision 1.6 1998/07/01 14:25:57 carl
- * strconcat was copying one byte too much
- * strcopy bugfix was using signed comparison
- + STRCOPY uses register calling conventions
- * FillChar bugfix was loading a word instead of a byte
- Revision 1.2 1998/03/27 23:48:06 carl
- * bugfix of STRCONCAT alignment problem
- Revision 1.18 1998/03/02 04:17:24 carl
- * problem with CHECK_OBJECT fixed, will probably only work with
- GNU tools, as the VMT pointer is an .lcomm and might not be
- zeroed automatically by other loaders.
- * CHECK_OBJECT was not jumping on right condition
- Revision 1.17 1998/02/23 02:26:06 carl
- * bugfix to make it link without problems
- Revision 1.13 1998/02/06 16:35:35 carl
- * oops commited wrong file
- Revision 1.11 1998/01/26 12:01:32 michael
- + Added log at the end
-
- Working file: rtl/m68k/m68k.inc
- description:
- ----------------------------
- revision 1.10
- date: 1998/01/19 10:21:36; author: michael; state: Exp; lines: +1 -12
- * moved Fillchar t(..,char) to system.inc
- ----------------------------
- revision 1.9
- date: 1998/01/13 03:47:39; author: carl; state: Exp; lines: +3 -3
- * bugfix of BoundsCheck invalid opcodes
- ----------------------------
- revision 1.8
- date: 1998/01/13 03:24:58; author: carl; state: Exp; lines: +2 -2
- * moveq.l #201 bugfix (This is of course an impossible opcode)
- ----------------------------
- revision 1.7
- date: 1998/01/12 15:24:47; author: carl; state: Exp; lines: +1 -20
- * bugfix, a function was being duplicated.
- ----------------------------
- revision 1.6
- date: 1998/01/12 03:40:11; author: carl; state: Exp; lines: +2 -2
- * bugfix of RE_OVERFLOW, now gives out a runerror(215)
- ----------------------------
- revision 1.5
- date: 1998/01/05 00:31:43; author: carl; state: Exp; lines: +206 -119
- * Bugfix of syntax errors
- ----------------------------
- revision 1.4
- date: 1998/01/01 16:50:16; author: michael; state: Exp; lines: +1 -21
- - Moved Do_exit to system.inc. Now processor independent.
- ----------------------------
- revision 1.3
- date: 1997/12/10 12:15:05; author: michael; state: Exp; lines: +2 -2
- * changed dateifunc to FileFunc.
- ----------------------------
- revision 1.2
- date: 1997/12/01 12:37:21; author: michael; state: Exp; lines: +14 -0
- + added copyright reference in header.
- ----------------------------
- revision 1.1
- date: 1997/11/27 08:33:48; author: michael; state: Exp;
- Initial revision
- ----------------------------
- revision 1.1.1.1
- date: 1997/11/27 08:33:48; author: michael; state: Exp; lines: +0 -0
- FPC RTL CVS start
- =============================================================================
- }
|