30
30
{****************************************************************************}
33
{ Don't call the following routines directly. }
34
Procedure Hlt;[public,alias: 'FPC_HALT_ERROR'];
35
{ called by code generator on run-time errors. }
36
{ on entry contains d0 = error code. }
38
b:byte; { only byte is used... }
49
Procedure FillChar(var x;count:longint;value:byte);[public,alias: 'FPC_FILL_OBJECT'];
52
move.l 8(a6), a0 { destination }
53
move.l 12(a6), d1 { number of bytes to fill }
54
move.b 16(a6),d0 { fill data }
55
cmpi.l #65535, d1 { check, if this is a word move }
56
ble @LMEMSET3 { use fast dbra mode }
64
bra @LMEMSET5 { finished slow mode , exit }
66
@LMEMSET4: { fast loop mode section 68010+ }
75
Procedure FillObject(var x; count: longint; value: byte);
78
move.l 8(a6), a0 { destination }
79
move.l 12(a6), d1 { number of bytes to fill }
80
move.w 16(a6),d0 { fill data }
81
cmp.l #65535, d1 { check, if this is a word move }
82
ble @LMEMSET3 { use fast dbra mode }
90
bra @LMEMSET5 { finished slow mode , exit }
92
@LMEMSET4: { fast loop mode section 68010+ }
101
procedure int_help_constructor;[public,alias:'FPC_HELP_CONSTRUCTOR'];
105
{ Entry without preamble, since we need the ESP of the
107
{ Stack (relative to %ebp):
113
{ do we have to initialize self }
114
{ we just need to check for zero }
116
tst.l d0 { set flags }
119
{ get memory, but save register first }
120
{ temporary variable }
128
{ push method pointer }
131
{ Restore all registers in the correct order }
133
{ Memory position to a5 }
136
{ If no memory available : fail() }
138
tst.l d0 { set flags for a5 }
140
{ init self for the constructor }
143
{ is there a VMT address ? }
147
{ In case the constructor doesn't do anything, the Zero-Flag }
148
{ can't be put, because this calls Fail() }
152
{ set zero inside the object }
162
{ Restore all registers in the correct order }
164
{ set the VMT address for the new created object }
165
{$ifdef OBJECTVMTOFFSET}
166
{ the offset is in %edi since the calling and has not been changed !! }
169
{$else OBJECTVMTOFFSET}
172
{$endif OBJECTVMTOFFSET}
186
procedure int_help_destructor;[public,alias:'FPC_HELP_DESTRUCTOR'];
190
{ Stack (relative to %ebp):
195
d0 contains vmt_offset
197
{ temporary Variable }
203
move.l 8(a6),d1 { Get the address of the vmt }
204
or.l d1,d1 { Check if there is a vmt }
206
{ Yes, get size from SELF! }
208
{ get VMT-pointer (from Self) to %ebx }
209
{$ifdef OBJECTVMTOFFSET}
210
{ the offset is in d0 since the calling and has not been changed !! }
212
{$else OBJECTVMTOFFSET}
214
{$endif OBJECTVMTOFFSET}
215
{ And put size on the Stack }
218
{ I think for precaution }
219
{ that we should clear the VMT here }
221
{ get address of local variable into }
228
{ Restore all registers in the correct order }
235
procedure new_class;assembler;[public,alias:'FPC_NEW_CLASS'];
246
{ call newinstance (class method!) }
248
{ new instance returns a pointer to the new created }
250
{ load a5 and insert self }
261
procedure dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS'];
270
{ no inherited call }
274
{ call freeinstance }
282
{ checks for a correct vmt pointer }
283
procedure int_check_object;assembler;[public,alias:'FPC_CHECK_OBJECT'];
284
{ ON ENTRY: a0 -> Pointer to the VMT }
285
{ Nota: All registers must be preserved including }
290
{ z flag set if zero }
306
function get_frame : longint; assembler;
312
function get_caller_addr(framebp:longint):longint;
324
function get_caller_frame(framebp:longint):longint;
33
procedure fpc_cpuinit;
37
{$define FPC_SYSTEM_HAS_GET_FRAME}
38
function get_frame : pointer; assembler;
44
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
45
function get_caller_addr(framebp : pointer) : pointer;
58
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
59
function get_caller_frame(framebp : pointer) : pointer;
72
{$define FPC_SYSTEM_HAS_SPTR}
73
function Sptr : Longint;
83
{$define FPC_SYSTEM_HAS_FILLCHAR}
84
procedure FillChar(var x;count:longint;value:byte);[public,alias: 'FPC_FILL_OBJECT'];
87
move.l 8(a6), a0 { destination }
88
move.l 12(a6), d1 { number of bytes to fill }
89
move.b 16(a6),d0 { fill data }
90
cmpi.l #65535, d1 { check, if this is a word move }
91
ble @LMEMSET3 { use fast dbra mode }
99
bra @LMEMSET5 { finished slow mode , exit }
101
@LMEMSET4: { fast loop mode section 68010+ }
107
end ['d0','d1','a0'];
337
112
{ procedure strcopy(dstr,sstr : pointer;len : longint);[public,alias: 'STRCOPY'];}
338
procedure strcopy; assembler;[public,alias: 'FPC_STRCOPY'];
339
{---------------------------------------------------}
340
{ Low-level routine to copy a string to another }
341
{ string with maximum length. Never call directly! }
343
{ a1.l = string to copy to }
344
{ a0.l = source string }
345
{ d0.l = maximum length of copy }
346
{ registers destroyed: a0,a1,d0,d1 }
347
{---------------------------------------------------}
113
procedure strcopy; assembler;[public,alias: 'FPC_STRCOPY'];
114
{---------------------------------------------------}
115
{ Low-level routine to copy a string to another }
116
{ string with maximum length. Never call directly! }
118
{ a1.l = string to copy to }
119
{ a0.l = source string }
120
{ d0.l = maximum length of copy }
121
{ registers destroyed: a0,a1,d0,d1 }
122
{---------------------------------------------------}
349
124
{ move.l 12(a6),a0
354
move.b (a0)+,d0 { Get source length }
356
cmp.w d1,d0 { This is a signed comparison! }
358
move.b d1,d0 { If longer than maximum size of target, cut
361
andi.l #$ff,d0 { zero extend d0-byte }
362
move.l d0,d1 { save length to copy }
363
move.b d0,(a1)+ { save new length }
364
{ Check if copying length is zero - if so then }
365
{ exit without copying anything. }
369
@LMSTRCOPY56: { 68010 Fast loop mode }
376
{ Concatenate Strings }
377
{ PARAMETERS ARE REVERSED COMPARED TO NORMAL! }
378
{ therefore online assembler may not parse the params as normal }
379
procedure strconcat(s1,s2 : pointer);[public,alias: 'STRCONCAT'];
384
move.l s1,a0 { a0 = destination }
385
move.l s2,a1 { a1 = source }
386
sub.b (a0),d0 { copyl:= 255 -length(s1) }
388
and.w #$ff,d0 { Sign flags are checked! }
390
cmp.w d6,d0 { if copyl > length(s2) then }
392
move.b (a1),d0 { copyl:=length(s2) }
396
lea 1(a0,d6),a0 { s1[length(s1)+1] }
397
add.l #1,a1 { s2[1] }
399
{ Check if copying length is zero - if so then }
400
{ exit without copying anything. }
405
move.b (a1)+,(a0)+ { s1[i] := s2[i]; }
409
add.b d0,(a0) { change to new string length }
411
end ['d0','d1','a0','a1','d6'];
415
{ DO NOT CALL directly. }
416
{ a0 = pointer to first string to compare }
417
{ a1 = pointer to second string to compare }
418
{ ALL FLAGS are set appropriately. }
419
{ ZF = strings are equal }
420
{ REGISTERS DESTROYED: a0, a1, d0, d1, d6 }
421
procedure strcmp; assembler;[public,alias:'FPC_STRCMP'];
423
move.b (a0)+,d0 { Get length of first string }
424
move.b (a1)+,d6 { Get length of 2nd string }
426
move.b d6,d1 { Save length of string for final compare }
428
cmp.b d0,d6 { Get shortest string length }
430
move.b d0,d6 { Set length to shortest string }
433
tst.b d6 { Both strings have a length of zero, exit }
439
subq.l #1,d6 { subtract first attempt }
440
{ if value is -1 then don't loop and just compare lengths of }
441
{ both strings before exiting. }
443
or.l d0,d0 { Make sure to set Zerfo flag to 0 }
445
{ Workaroung for GAS v.134 bug }
446
{ old: cmp.b (a1)+,(a0)+ }
449
dbne d6,@LSTRCONCAT5 { Repeat until not equal }
452
{ If length of both string are equal }
453
{ Then set zero flag }
454
cmp.b d1,d0 { Compare length - set flag if equal length strings }
459
Function strpas(p: pchar): string;
460
{ only 255 first characters are actually copied. }
467
while (ord(p[counter]) <> 0) and (counter < 255) do
470
str[counter] := char(p[counter-1]);
472
str[0] := char(counter);
476
function strlen(p : pchar) : longint;
483
until ord(p[counter]) = 0;
488
procedure move(var source;var dest;count : longint);
489
{ base pointer+8 = source }
490
{ base pointer+12 = destination }
491
{ base pointer+16 = number of bytes to move}
495
move.l 16(a6),d0 { number of bytes }
497
move.l 12(a6),a1 { destination }
498
move.l 8(a6),a0 { source }
500
cmpi.l #65535, d0 { check, if this is a word move }
501
ble @LMEMSET00 { use fast dbra mode 68010+ }
503
cmp.l a0,a1 { check copy direction }
505
add.l d0,a0 { move pointers to end }
509
move.b -(a0),-(a1) { (s < d) copy loop }
516
move.b (a0)+,(a1)+ { (s >= d) copy loop }
523
@LMEMSET00: { use fast loop mode 68010+ }
524
cmp.l a0,a1 { check copy direction }
526
add.l d0,a0 { move pointers to end }
530
move.b -(a0),-(a1) { (s < d) copy loop }
535
move.b (a0)+,(a1)+ { (s >= d) copy loop }
538
{ end fast loop mode }
540
end ['d0','a0','a1'];
544
procedure fillword(var x;count : longint;value : word);
548
move.l 8(a6), a0 { destination }
549
move.l 12(a6), d1 { number of bytes to fill }
550
move.w 16(a6),d0 { fill data }
558
end ['d0','d1','a0'];
562
function abs(l : longint) : longint;
575
function odd(l : longint) : boolean;
578
if (l and $01) = $01 then
584
function sqr(l : longint) : longint;
590
procedure int_str(l : longint;var s : string);
605
{ handle case where l = 0 }
618
{ handle non-zero case }
621
s:=char((value mod 10)+ord('0'))+s;
622
value := value div 10;
629
Function Sptr : Longint;
641
Procedure BoundsCheck;assembler;[public,alias:'FPC_RE_BOUNDS_CHECK'];
642
{ called by code generator with R+ state to }
643
{ determine if a range check occured. }
644
{ Only in 68000 mode, in 68020 mode this is }
647
{ A1 = address contaning min and max indexes }
648
{ D0 = value of current index to check. }
650
cmp.l (A1),D0 { lower bound ... }
651
bmi @rebounderr { is index lower ... }
662
{****************************************************************************
664
****************************************************************************}
666
procedure int_iocheck(addr : longint);[public,alias: {$ifdef FPCNAMES}'FPC_'+{$endif}'IOCHECK'];
677
If ErrorProc<>Nil then
678
TErrorProc(Errorproc)(l,pointer(addr));
680
writeln('IO-Error ',l,' at 0x',HexStr(addr,8));
129
move.b (a0)+,d0 { Get source length }
131
cmp.w d1,d0 { This is a signed comparison! }
133
move.b d1,d0 { If longer than maximum size of target, cut
136
andi.l #$ff,d0 { zero extend d0-byte }
137
move.l d0,d1 { save length to copy }
138
move.b d0,(a1)+ { save new length }
139
{ Check if copying length is zero - if so then }
140
{ exit without copying anything. }
144
@LMSTRCOPY56: { 68010 Fast loop mode }
152
{ Concatenate Strings }
153
{ PARAMETERS ARE REVERSED COMPARED TO NORMAL! }
154
{ therefore online assembler may not parse the params as normal }
155
procedure strconcat(s1,s2 : pointer);[public,alias: 'STRCONCAT'];
159
move.l s1,a0 { a0 = destination }
160
move.l s2,a1 { a1 = source }
161
sub.b (a0),d0 { copyl:= 255 -length(s1) }
163
and.w #$ff,d0 { Sign flags are checked! }
165
cmp.w d6,d0 { if copyl > length(s2) then }
167
move.b (a1),d0 { copyl:=length(s2) }
171
lea 1(a0,d6),a0 { s1[length(s1)+1] }
172
add.l #1,a1 { s2[1] }
174
{ Check if copying length is zero - if so then }
175
{ exit without copying anything. }
180
move.b (a1)+,(a0)+ { s1[i] := s2[i]; }
184
add.b d0,(a0) { change to new string length }
186
end ['d0','d1','a0','a1','d6'];
190
{ DO NOT CALL directly. }
191
{ a0 = pointer to first string to compare }
192
{ a1 = pointer to second string to compare }
193
{ ALL FLAGS are set appropriately. }
194
{ ZF = strings are equal }
195
{ REGISTERS DESTROYED: a0, a1, d0, d1, d6 }
196
procedure strcmp; assembler;[public,alias:'FPC_STRCMP'];
198
move.b (a0)+,d0 { Get length of first string }
199
move.b (a1)+,d6 { Get length of 2nd string }
201
move.b d6,d1 { Save length of string for final compare }
203
cmp.b d0,d6 { Get shortest string length }
205
move.b d0,d6 { Set length to shortest string }
208
tst.b d6 { Both strings have a length of zero, exit }
214
subq.l #1,d6 { subtract first attempt }
215
{ if value is -1 then don't loop and just compare lengths of }
216
{ both strings before exiting. }
218
or.l d0,d0 { Make sure to set Zerfo flag to 0 }
220
{ Workaroung for GAS v.134 bug }
221
{ old: cmp.b (a1)+,(a0)+ }
224
dbne d6,@LSTRCONCAT5 { Repeat until not equal }
227
{ If length of both string are equal }
228
{ Then set zero flag }
229
cmp.b d1,d0 { Compare length - set flag if equal length strings }
235
{$define FPC_SYSTEM_HAS_MOVE}
236
procedure move(var source;var dest;count : longint);
237
{ base pointer+8 = source }
238
{ base pointer+12 = destination }
239
{ base pointer+16 = number of bytes to move}
243
move.l 16(a6),d0 { number of bytes }
245
move.l 12(a6),a1 { destination }
246
move.l 8(a6),a0 { source }
248
cmpi.l #65535, d0 { check, if this is a word move }
249
ble @LMEMSET00 { use fast dbra mode 68010+ }
251
cmp.l a0,a1 { check copy direction }
253
add.l d0,a0 { move pointers to end }
257
move.b -(a0),-(a1) { (s < d) copy loop }
264
move.b (a0)+,(a1)+ { (s >= d) copy loop }
271
@LMEMSET00: { use fast loop mode 68010+ }
272
cmp.l a0,a1 { check copy direction }
274
add.l d0,a0 { move pointers to end }
278
move.b -(a0),-(a1) { (s < d) copy loop }
283
move.b (a0)+,(a1)+ { (s >= d) copy loop }
286
{ end fast loop mode }
288
end ['d0','a0','a1'];
292
{$define FPC_SYSTEM_HAS_FILLWORD}
293
procedure fillword(var x;count : longint;value : word);
296
move.l 8(a6), a0 { destination }
297
move.l 12(a6), d1 { number of bytes to fill }
298
move.w 16(a6),d0 { fill data }
306
end ['d0','d1','a0'];
310
{$define FPC_SYSTEM_HAS_ABS_LONGINT}
311
function abs(l : longint) : longint;
690
325
$Log: m68k.inc,v $
691
Revision 1.1 2000/07/13 06:30:56 michael
694
Revision 1.17 2000/01/07 16:41:42 daniel
697
Revision 1.16 2000/01/07 16:32:29 daniel
698
* copyright 2000 added
700
Revision 1.15 1998/10/17 14:34:37 carl
701
* FillChar and FillObject bugfix, count was compared with byte
703
Revision 1.14 1998/10/16 13:37:45 pierre
704
* added code for vmt_offset in destructors
706
Revision 1.13 1998/10/15 11:35:03 pierre
707
+ first step of variable vmt offset
708
offset is stored in R_EDI (R_D0)
709
if objectvmtoffset is defined
711
Revision 1.12 1998/10/13 08:00:06 pierre
712
* some bugs related to FPC_ prefix fixed
713
* problems with pbyte sometimes defined and sometimes not for rttip.inc solved
715
Revision 1.11 1998/09/14 10:48:29 peter
717
* Heap manager is now system independent
719
Revision 1.10 1998/08/17 12:26:04 carl
720
+ simple cleanup of comments
722
Revision 1.9 1998/07/30 13:26:14 michael
723
+ Added support for ErrorProc variable. All internal functions are required
724
to call HandleError instead of runerror from now on.
725
This is necessary for exception support.
727
Revision 1.8 1998/07/10 11:02:41 peter
728
* support_fixed, becuase fixed is not 100% yet for the m68k
730
Revision 1.7 1998/07/02 12:20:58 carl
731
+ Io-Error and overflow print erroraddr in hex now
733
Revision 1.6 1998/07/01 14:25:57 carl
734
* strconcat was copying one byte too much
735
* strcopy bugfix was using signed comparison
736
+ STRCOPY uses register calling conventions
737
* FillChar bugfix was loading a word instead of a byte
326
Revision 1.5 2004/05/23 12:42:42 florian
327
+ added currency and widestring support to TWriter and TReader
329
Revision 1.4 2004/01/02 17:22:14 jonas
330
+ fpc_cpuinit procedure to allow cpu/fpu initialisation before any unit
332
+ fpu exceptions for invalid operations and division by zero enabled for
335
Revision 1.3 2002/09/07 16:01:20 peter
336
* old logs removed and tabs fixed