home *** CD-ROM | disk | FTP | other *** search
- {
- $Id: cga68k.pas,v 1.2.2.7 1998/08/14 12:04:36 carl Exp $
- Copyright (c) 1993-98 by Florian Klaempfl, Carl Eric Codere
-
- This unit generates 68000 (or better) assembler from the parse tree
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- 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. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ****************************************************************************
- }
- unit cga68k;
-
- interface
-
- uses
- objects,cobjects,verbose,systems,globals,tree,symtable,types,strings,
- pass_1,hcodegen,aasm,m68k,tgen68k,files,gdb;
-
- procedure emitl(op : tasmop;var l : plabel);
- procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
- procedure emitcall(const routine:string;add_to_externals : boolean);
- procedure emitloadord2reg(location:Tlocation;orddef:Porddef;
- destreg:Tregister;delloc:boolean);
- { produces jumps to true respectively false labels using boolean expressions }
- procedure maketojumpbool(p : ptree);
- procedure emitoverflowcheck(p: ptree);
- procedure push_int(l : longint);
- function maybe_push(needed : byte;p : ptree) : boolean;
- procedure restore(p : ptree);
- procedure emit_push_mem(const ref : treference);
- procedure emitpushreferenceaddr(const ref : treference);
- procedure swaptree(p: ptree);
- procedure copystring(const dref,sref : treference;len : byte);
- procedure concatcopy(source,dest : treference;size : longint;delsource : boolean);
- { see implementation }
- procedure maybe_loada5;
- procedure emit_bounds_check(hp: treference; index: tregister);
- procedure loadstring(p:ptree);
-
- procedure floatload(t : tfloattype;const ref : treference; var location:tlocation);
- { return a float op_size from a floatb type }
- { also does some error checking for problems }
- function getfloatsize(t: tfloattype): topsize;
- procedure floatstore(t : tfloattype;var location:tlocation; const ref:treference);
- { procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
- procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize); }
-
- procedure firstcomplex(p : ptree);
- procedure secondfuncret(var p : ptree);
-
- { initialize respectively terminates the code generator }
- { for a new module or procedure }
- procedure codegen_doneprocedure;
- procedure codegen_donemodule;
- procedure codegen_newmodule;
- procedure codegen_newprocedure;
-
- { generate entry code for a procedure.}
- procedure genentrycode(const proc_names:Tstringcontainer;make_global:boolean;
- stackframe:longint;
- var parasize:longint;var nostackframe:boolean);
- { generate the exit code for a procedure. }
- procedure genexitcode(parasize:longint;nostackframe:boolean);
-
-
- implementation
-
- {
- procedure genconstadd(size : topsize;l : longint;const str : string);
-
- begin
- if l=0 then
- else if l=1 then
- exprasmlist^.concat(new(pai68k,op_A_INC,size,str)
- else if l=-1 then
- exprasmlist^.concat(new(pai68k,op_A_INC,size,str)
- else
- exprasmlist^.concat(new(pai68k,op_ADD,size,'$'+tostr(l)+','+str);
- end;
- }
- procedure copystring(const dref,sref : treference;len : byte);
-
- var
- pushed : tpushed;
-
- begin
- pushusedregisters(pushed,$ffff);
- { emitpushreferenceaddr(dref); }
- { emitpushreferenceaddr(sref); }
- { push_int(len); }
- { This speeds up from 116 cycles to 24 cycles on the 68000 }
- { when passing register parameters! }
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(dref),R_A1)));
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(sref),R_A0)));
- exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,len,R_D0)));
- emitcall('STRCOPY',true);
- maybe_loada5;
- popusedregisters(pushed);
- end;
-
-
- procedure loadstring(p:ptree);
- begin
- case p^.right^.resulttype^.deftype of
- stringdef : begin
- { load a string ... }
- { here two possible choices: }
- { if it is a char, then simply }
- { load 0 length string }
- if (p^.right^.treetype=stringconstn) and
- (p^.right^.values^='') then
- exprasmlist^.concat(new(pai68k,op_const_ref(
- A_MOVE,S_B,0,newreference(p^.left^.location.reference))))
- else
- copystring(p^.left^.location.reference,p^.right^.location.reference,
- min(pstringdef(p^.right^.resulttype)^.len,pstringdef(p^.left^.resulttype)^.len));
- end;
- orddef : begin
- if p^.right^.treetype=ordconstn then
- begin
- { offset 0: length of string }
- { offset 1: character }
- exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_W,1*256+p^.right^.value,
- newreference(p^.left^.location.reference))))
- end
- else
- begin
- { not so elegant (goes better with extra register }
- if (p^.right^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
- begin
- exprasmlist^.concat(new(pai68k,op_reg_reg(
- A_MOVE,S_B,p^.right^.location.register,R_D0)));
- ungetregister32(p^.right^.location.register);
- end
- else
- begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(
- A_MOVE,S_B,newreference(p^.right^.location.reference),R_D0)));
- del_reference(p^.right^.location.reference);
- end;
- { alignment can cause problems }
- { add length of string to ref }
- exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,1,
- newreference(p^.left^.location.reference))));
- (* if abs(p^.left^.location.reference.offset) >= 1 then
- Begin *)
- { temporarily decrease offset }
- Inc(p^.left^.location.reference.offset);
- exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_B,R_D0,
- newreference(p^.left^.location.reference))));
- Dec(p^.left^.location.reference.offset);
- { restore offset }
- (* end
- else
- Begin
- Comment(V_Debug,'SecondChar2String() internal error.');
- internalerror(34);
- end; *)
- end;
- end;
- else
- Message(sym_e_type_mismatch);
- end;
- end;
-
-
-
-
-
- procedure restore(p : ptree);
-
- var
- hregister : tregister;
-
- begin
- if (p^.location.loc=LOC_REGISTER) or (p^.location.loc=LOC_CREGISTER) then
- hregister:=getregister32
- else
- hregister:=getaddressreg;
-
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_SPPULL,hregister)));
- if (p^.location.loc=LOC_REGISTER) or (p^.location.loc=LOC_CREGISTER) then
- begin
- p^.location.register:=hregister;
- end
- else
- begin
- reset_reference(p^.location.reference);
- p^.location.reference.base:=hregister;
- set_location(p^.left^.location,p^.location);
- end;
- end;
-
- function maybe_push(needed : byte;p : ptree) : boolean;
-
- var
- pushed : boolean;
- {hregister : tregister; }
- reg: tregister;
- begin
- if (needed>usablereg32) or (needed > usableaddress) then
- begin
- if (p^.location.loc=LOC_REGISTER) or
- (p^.location.loc=LOC_CREGISTER) then
- begin
- pushed:=true;
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,p^.location.register,R_SPPUSH)));
- ungetregister32(p^.location.register);
- end
- else
- if ((p^.location.loc=LOC_MEM) or(p^.location.loc=LOC_REFERENCE)) and
- ((p^.location.reference.base<>R_NO) or
- (p^.location.reference.index<>R_NO)) then
- begin
- del_reference(p^.location.reference);
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
- R_A0)));
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A0,R_SPPUSH)));
- pushed:=true;
- end
- else pushed:=false;
- end
- else pushed:=false;
- maybe_push:=pushed;
- end;
-
-
- { emit out of range check for arrays and sets}
- procedure emit_bounds_check(hp: treference; index: tregister);
- { index = index of array to check }
- { memory of range check information for array }
- var
- hl : plabel;
- begin
- if (opt_processors = MC68020) then
- begin
- exprasmlist^.concat(new(pai68k, op_ref_reg(A_CMP2,S_L,newreference(hp),index)));
- getlabel(hl);
- emitl(A_BCC, hl);
- exprasmlist^.concat(new(pai68k, op_const_reg(A_MOVE,S_L,201,R_D0)));
- emitcall('HALT_ERROR',true);
- emitl(A_LABEL, hl);
- end
- else
- begin
- exprasmlist^.concat(new(pai68k, op_ref_reg(A_LEA,S_L,newreference(hp), R_A1)));
- exprasmlist^.concat(new(pai68k, op_reg_reg(A_MOVE, S_L, index, R_D0)));
- emitcall('RE_BOUNDS_CHECK',true);
- end;
- end;
-
-
-
- function getfloatsize(t: tfloattype): topsize;
- begin
- case t of
- s32real: getfloatsize := S_S;
- s64real: getfloatsize := S_Q;
- s80real: getfloatsize := S_X;
- {$ifdef extdebug}
- else {else case }
- begin
- Comment(V_Debug,' getfloatsize() trying to get unknown size.');
- internalerror(12);
- end;
- {$endif}
- end;
- end;
-
- procedure emitl(op : tasmop;var l : plabel);
-
- begin
- if op=A_LABEL then
- exprasmlist^.concat(new(pai_label,init(l)))
- else
- exprasmlist^.concat(new(pai_labeled,init(op,l)))
- end;
-
- procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
-
- begin
- if (reg1 <> reg2) or (i <> A_MOVE) then
- exprasmlist^.concat(new(pai68k,op_reg_reg(i,s,reg1,reg2)));
- end;
-
-
- procedure emitcall(const routine:string;add_to_externals : boolean);
-
- begin
- exprasmlist^.concat(new(pai68k,op_csymbol(A_JSR,S_NO,newcsymbol(routine,0))));
- if assem_need_external_list and add_to_externals and
- not (cs_compilesystem in aktswitches) then
- concat_external(routine,EXT_NEAR);
- end;
-
-
- procedure maketojumpbool(p : ptree);
-
- begin
- if p^.error then
- exit;
- if (p^.resulttype^.deftype=orddef) and
- (porddef(p^.resulttype)^.typ=bool8bit) then
- begin
- if is_constboolnode(p) then
- begin
- if p^.value<>0 then
- emitl(A_JMP,truelabel)
- else emitl(A_JMP,falselabel);
- end
- else
- begin
- case p^.location.loc of
- LOC_CREGISTER,LOC_REGISTER : begin
- exprasmlist^.concat(new(pai68k,op_reg(A_TST,S_B,p^.location.register)));
- ungetregister32(p^.location.register);
- emitl(A_BNE,truelabel);
- emitl(A_JMP,falselabel);
- end;
- LOC_MEM,LOC_REFERENCE : begin
- exprasmlist^.concat(new(pai68k,op_ref(
- A_TST,S_B,newreference(p^.location.reference))));
- del_reference(p^.location.reference);
- emitl(A_BNE,truelabel);
- emitl(A_JMP,falselabel);
- end;
- LOC_FLAGS : begin
- emitl(flag_2_jmp[p^.location.resflags],truelabel);
- emitl(A_JMP,falselabel);
- end;
- end;
- end;
- end
- else
- Message(sym_e_type_mismatch);
- end;
-
- procedure emitoverflowcheck(p: ptree);
-
- var
- hl : plabel;
-
- begin
- if cs_check_overflow in aktswitches then
- begin
- getlabel(hl);
- if not ((p^.resulttype^.deftype=pointerdef) or
- ((p^.resulttype^.deftype=orddef) and
- (porddef(p^.resulttype)^.typ in [u16bit,u32bit,u8bit,uchar,bool8bit]))) then
- emitl(A_BVC,hl)
- else
- emitl(A_BCC,hl);
- emitcall('RE_OVERFLOW',true);
- emitl(A_LABEL,hl);
- end;
- end;
-
-
- procedure push_int(l : longint);
-
- begin
- if (l = 0) and (opt_processors = MC68020) then
- begin
- exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_L,R_D6)));
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
- R_D6, R_SPPUSH)));
- end
- else
- if not(cs_littlesize in aktswitches) and (l >= -128) and (l <= 127) then
- begin
- exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVEQ,S_L,l,R_D6)));
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D6,R_SPPUSH)));
- end
- else
- exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,l,R_SPPUSH)));
- end;
-
- procedure emit_push_mem(const ref : treference);
- { Push a value on to the stack }
- begin
- if ref.isintvalue then
- push_int(ref.offset)
- else
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(ref),R_SPPUSH)));
- end;
-
-
- { USES REGISTER R_A1 }
- procedure emitpushreferenceaddr(const ref : treference);
- { Push a pointer to a value on the stack }
- begin
- if ref.isintvalue then
- push_int(ref.offset)
- else
- begin
- if (ref.base=R_NO) and (ref.index=R_NO) then
- exprasmlist^.concat(new(pai68k,op_ref(A_PEA,S_L,
- newreference(ref))))
- else if (ref.base=R_NO) and (ref.index<>R_NO) and
- (ref.offset=0) and (ref.scalefactor=0) and (ref.symbol=nil) then
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
- ref.index,R_SPPUSH)))
- else if (ref.base<>R_NO) and (ref.index=R_NO) and
- (ref.offset=0) and (ref.symbol=nil) then
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,ref.base,R_SPPUSH)))
- else
- begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(ref),R_A1)));
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A1,R_SPPUSH)));
- end;
- end;
- end;
-
- procedure swaptree(p:Ptree);
-
- var swapp:Ptree;
-
- begin
- swapp:=p^.right;
- p^.right:=p^.left;
- p^.left:=swapp;
- p^.swaped:=not(p^.swaped);
- end;
-
-
- procedure genentrycode(const proc_names:Tstringcontainer;make_global:boolean;
- stackframe:longint;
- var parasize:longint;var nostackframe:boolean);
-
- {Generates the entry code for a procedure.}
-
- var hs:string;
- hp:Pused_unit;
- unitinits:taasmoutput;
- {$ifdef GDB}
- oldaktprocname : string;
- stab_function_name:Pai_stab_function_name;
- {$endif GDB}
- begin
- if (aktprocsym^.definition^.options and poproginit<>0) then
- begin
- {Init the stack checking.}
- if (cs_check_stack in aktswitches) and
- (target_info.target=target_linux) then
- begin
- procinfo.aktentrycode^.insert(new(pai68k,
- op_csymbol(A_JSR,S_NO,newcsymbol('INIT_STACK_CHECK',0))));
- end
- else
- { The main program has already allocated its stack - so we simply compare }
- { with a value of ZERO, and the comparison will directly check! }
- if (cs_check_stack in aktswitches) then
- begin
- procinfo.aktentrycode^.insert(new(pai68k,op_csymbol(A_JSR,S_NO,
- newcsymbol('STACKCHECK',0))));
- procinfo.aktentrycode^.insert(new(pai68k,op_const_reg(A_MOVE,S_L,
- 0,R_D0)));
- concat_external('STACKCHECK',EXT_NEAR);
- end;
-
-
- unitinits.init;
-
- {Call the unit init procedures.}
- hp:=pused_unit(usedunits.first);
- while assigned(hp) do
- begin
- { call the unit init code and make it external }
- if (hp^.u^.flags and uf_init)<>0 then
- begin
- unitinits.concat(new(pai68k,op_csymbol(A_JSR,S_NO,newcsymbol('INIT$$'+hp^.u^.unitname^,0))));
- externals^.concat(new(pai_external,init('INIT$$'+hp^.u^.unitname^,EXT_NEAR)));
- end;
- hp:=pused_unit(hp^.next);
- end;
- procinfo.aktentrycode^.insertlist(@unitinits);
- unitinits.done;
- end;
-
- { a constructor needs a help procedure }
- if (aktprocsym^.definition^.options and poconstructor)<>0 then
- begin
- if procinfo._class^.isclass then
- begin
- procinfo.aktentrycode^.insert(new(pai_labeled,init(A_BEQ,quickexitlabel)));
- procinfo.aktentrycode^.insert(new(pai68k,op_csymbol(A_JSR,S_NO,
- newcsymbol('NEW_CLASS',0))));
- concat_external('NEW_CLASS',EXT_NEAR);
- end
- else
- begin
- procinfo.aktentrycode^.insert(new(pai_labeled,init(A_BEQ,quickexitlabel)));
- procinfo.aktentrycode^.insert(new(pai68k,op_csymbol(A_JSR,S_NO,
- newcsymbol('HELP_CONSTRUCTOR',0))));
- concat_external('HELP_CONSTRUCTOR',EXT_NEAR);
- end;
- end;
- { don't load ESI, does the caller }
-
- { omit stack frame ? }
- if procinfo.framepointer=stack_pointer then
- begin
- Message(cg_d_stackframe_omited);
- nostackframe:=true;
- if (aktprocsym^.definition^.options and (pounitinit or poproginit)<>0) then
- parasize:=0
- else
- parasize:=aktprocsym^.definition^.parast^.datasize+procinfo.call_offset;
- end
- else
- begin
- if (aktprocsym^.definition^.options and (pounitinit or poproginit)<>0) then
- parasize:=0
- else
- parasize:=aktprocsym^.definition^.parast^.datasize+procinfo.call_offset-8;
- nostackframe:=false;
- if stackframe<>0 then
- begin
- if cs_littlesize in aktswitches then
- begin
- if (cs_check_stack in aktswitches) and
- (target_info.target<>target_linux) then
- begin
- { If only not in main program, do we setup stack checking }
- if (aktprocsym^.definition^.options and poproginit=0) then
- Begin
- procinfo.aktentrycode^.insert(new(pai68k,
- op_csymbol(A_JSR,S_NO,newcsymbol('STACKCHECK',0))));
- procinfo.aktentrycode^.insert(new(pai68k,op_const_reg(A_MOVE,S_L,stackframe,R_D0)));
- concat_external('STACKCHECK',EXT_NEAR);
- end;
- end;
- { to allocate stack space }
- { here we allocate space using link signed 16-bit version }
- { -ve offset to allocate stack space! }
- if (stackframe > -32767) and (stackframe < 32769) then
- procinfo.aktentrycode^.insert(new(pai68k,op_reg_const(A_LINK,S_W,R_A6,-stackframe)))
- else
- Message(cg_e_stacklimit_in_local_routine);
- end
- else
- begin
- { Not to complicate the code generator too much, and since some }
- { of the systems only support this format, the stackframe cannot }
- { exceed 32K in size. }
- if (stackframe > -32767) and (stackframe < 32769) then
- begin
- procinfo.aktentrycode^.insert(new(pai68k,op_const_reg(A_SUB,S_L,stackframe,R_SP)));
- { IF only NOT in main program do we check the stack normally }
- if (cs_check_stack in aktswitches)
- and (aktprocsym^.definition^.options and poproginit=0) then
- begin
- procinfo.aktentrycode^.insert(new(pai68k,
- op_csymbol(A_JSR,S_NO,newcsymbol('STACKCHECK',0))));
- procinfo.aktentrycode^.insert(new(pai68k,op_const_reg(A_MOVE,S_L,
- stackframe,R_D0)));
- concat_external('STACKCHECK',EXT_NEAR);
- end;
- procinfo.aktentrycode^.insert(new(pai68k,op_reg_reg(A_MOVE,S_L,R_SP,R_A6)));
- procinfo.aktentrycode^.insert(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A6,R_SPPUSH)));
- end
- else
- Message(cg_e_stacklimit_in_local_routine);
- end;
- end {endif stackframe<>0 }
- else
- begin
- procinfo.aktentrycode^.insert(new(pai68k,op_reg_reg(A_MOVE,S_L,R_SP,R_A6)));
- procinfo.aktentrycode^.insert(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A6,R_SPPUSH)));
- end;
- end;
-
-
- if (aktprocsym^.definition^.options and pointerrupt)<>0 then
- generate_interrupt_stackframe_entry;
-
- {proc_names.insert(aktprocsym^.definition^.mangledname);}
-
- if (aktprocsym^.definition^.owner^.symtabletype=globalsymtable) or
- ((procinfo._class<>nil) and (procinfo._class^.owner^.
- symtabletype=globalsymtable)) then
- make_global:=true;
- hs:=proc_names.get;
-
- {$IfDef GDB}
- if (cs_debuginfo in aktswitches) and
- target_info.use_function_relative_addresses then
- stab_function_name := new(pai_stab_function_name,init(strpnew(hs)));
- oldaktprocname:=aktprocsym^.name;
- {$EndIf GDB}
-
-
- while hs<>'' do
- begin
- if make_global then
- procinfo.aktentrycode^.insert(new(pai_symbol,init_global(hs)))
- else
- procinfo.aktentrycode^.insert(new(pai_symbol,init(hs)));
- {$ifdef GDB}
- if (cs_debuginfo in aktswitches) and
- target_info.use_function_relative_addresses then
- begin
- procinfo.aktentrycode^.insert(new(pai_stab_function_name,init(strpnew(hs))));
- { This is not a nice solution to save the name, change it and restore when done }
- aktprocsym^.setname(hs);
- procinfo.aktentrycode^.insert(new(pai_stabs,init(aktprocsym^.stabstring)));
- end;
- {$endif GDB}
- hs:=proc_names.get;
- end;
- {$ifdef GDB}
- aktprocsym^.setname(oldaktprocname);
-
- if (cs_debuginfo in aktswitches) then
- begin
- if target_info.use_function_relative_addresses then
- procinfo.aktentrycode^.insert(stab_function_name);
- if make_global or ((procinfo.flags and pi_is_global) <> 0) then
- aktprocsym^.is_global := True;
- aktprocsym^.isstabwritten:=true;
- end;
- {$endif GDB}
- { Alignment required for Motorola }
- procinfo.aktentrycode^.insert(new(pai_align,init(2)));
- {$ifdef extdebug}
- procinfo.aktentrycode^.insert(new(pai_direct,init(strpnew(target_info.newline))));
- {$endif extdebug}
- end;
-
- {Generate the exit code for a procedure.}
- procedure genexitcode(parasize:longint;nostackframe:boolean);
-
- var hr:Preference; {This is for function results.}
- op:Tasmop;
- s:Topsize;
-
- begin
- { !!!! insert there automatic destructors }
-
- procinfo.aktexitcode^.insert(new(pai_label,init(aktexitlabel)));
-
- { call the destructor help procedure }
- if (aktprocsym^.definition^.options and podestructor)<>0 then
- begin
- if procinfo._class^.isclass then
- begin
- procinfo.aktexitcode^.insert(new(pai68k,op_csymbol(A_JSR,S_NO,
- newcsymbol('DISPOSE_CLASS',0))));
- concat_external('DISPOSE_CLASS',EXT_NEAR);
- end
- else
- begin
- procinfo.aktexitcode^.insert(new(pai68k,op_csymbol(A_JSR,S_NO,
- newcsymbol('HELP_DESTRUCTOR',0))));
- concat_external('HELP_DESTRUCTOR',EXT_NEAR);
- end;
- end;
-
- { call __EXIT for main program }
- { ????????? }
- if ((aktprocsym^.definition^.options and poproginit)<>0) and
- (target_info.target<>target_PalmOS) then
- begin
- procinfo.aktexitcode^.concat(new(pai68k,op_csymbol(A_JSR,S_NO,newcsymbol('__EXIT',0))));
- externals^.concat(new(pai_external,init('__EXIT',EXT_NEAR)));
- end;
-
- { handle return value }
- if (aktprocsym^.definition^.options and poassembler)=0 then
- if (aktprocsym^.definition^.options and poconstructor)=0 then
- begin
- if procinfo.retdef<>pdef(voiddef) then
- begin
- if not procinfo.funcret_is_valid then
- Message(sym_w_function_result_not_set);
- new(hr);
- reset_reference(hr^);
- hr^.offset:=procinfo.retoffset;
- hr^.base:=procinfo.framepointer;
- if (procinfo.retdef^.deftype=orddef) then
- begin
- case porddef(procinfo.retdef)^.typ of
- s32bit,u32bit :
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hr,R_D0)));
- u8bit,s8bit,uchar,bool8bit :
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,hr,R_D0)));
- s16bit,u16bit :
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,hr,R_D0)));
- end;
- end
- else
- if (procinfo.retdef^.deftype in [pointerdef,enumdef,procvardef]) or
- ((procinfo.retdef^.deftype=setdef) and
- (psetdef(procinfo.retdef)^.settype=smallset)) then
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hr,R_D0)))
- else
- if (procinfo.retdef^.deftype=floatdef) then
- begin
- if pfloatdef(procinfo.retdef)^.typ=f32bit then
- begin
- { Isnt this missing ? }
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hr,R_D0)));
- end
- else
- begin
- { how the return value is handled }
- { if single value, then return in d0, otherwise return in }
- { TRUE FPU register (does not apply in emulation mode) }
- if (pfloatdef(procinfo.retdef)^.typ = s32real) then
- begin
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_MOVE,
- S_L,hr,R_D0)))
- end
- else
- begin
- if cs_fp_emulation in aktswitches then
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_MOVE,
- S_L,hr,R_D0)))
- else
- procinfo.aktexitcode^.concat(new(pai68k,op_ref_reg(A_FMOVE,
- getfloatsize(pfloatdef(procinfo.retdef)^.typ),hr,R_FP0)));
- end;
- end;
- end
- else
- dispose(hr);
- end
- end
- else
- begin
- { successful constructor deletes the zero flag }
- { and returns self in accumulator }
- procinfo.aktexitcode^.concat(new(pai_label,init(quickexitlabel)));
- { eax must be set to zero if the allocation failed !!! }
- procinfo.aktexitcode^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_A5,R_D0)));
- { faster then OR on mc68000/mc68020 }
- procinfo.aktexitcode^.concat(new(pai68k,op_reg(A_TST,S_L,R_D0)));
- end;
- procinfo.aktexitcode^.concat(new(pai_label,init(aktexit2label)));
- if not(nostackframe) then
- procinfo.aktexitcode^.concat(new(pai68k,op_reg(A_UNLK,S_NO,R_A6)));
-
- { at last, the return is generated }
-
- if (aktprocsym^.definition^.options and pointerrupt)<>0 then
- generate_interrupt_stackframe_exit
- else
- if (parasize=0) or ((aktprocsym^.definition^.options and poclearstack)<>0)
- then
- {Routines with the poclearstack flag set use only a ret.}
- { also routines with parasize=0 }
- procinfo.aktexitcode^.concat(new(pai68k,op_none(A_RTS,S_NO)))
- else
- { return with immediate size possible here }
- { signed! }
- if (opt_processors = MC68020) and (parasize < $7FFF) then
- procinfo.aktexitcode^.concat(new(pai68k,op_const(
- A_RTD,S_NO,parasize)))
- { manually restore the stack }
- else
- begin
- { We must pull the PC Counter from the stack, before }
- { restoring the stack pointer, otherwise the PC would }
- { point to nowhere! }
-
- { save the PC counter (pop it from the stack) }
- procinfo.aktexitcode^.concat(new(pai68k,op_reg_reg(
- A_MOVE,S_L,R_SPPULL,R_A0)));
- { can we do a quick addition ... }
- if (parasize > 0) and (parasize < 9) then
- procinfo.aktexitcode^.concat(new(pai68k,op_const_reg(
- A_ADD,S_L,parasize,R_SP)))
- else { nope ... }
- procinfo.aktexitcode^.concat(new(pai68k,op_const_reg(
- A_ADD,S_L,parasize,R_SP)));
- { endif }
- { restore the PC counter (push it on the stack) }
- procinfo.aktexitcode^.concat(new(pai68k,op_reg_reg(
- A_MOVE,S_L,R_A0,R_SPPUSH)));
- procinfo.aktexitcode^.concat(new(pai68k,op_none(
- A_RTS,S_NO)))
- end;
- {$ifdef GDB}
- if cs_debuginfo in aktswitches then
- begin
- aktprocsym^.concatstabto(procinfo.aktexitcode);
- if assigned(procinfo._class) then
- procinfo.aktexitcode^.concat(new(pai_stabs,init(strpnew(
- '"$t:v'+procinfo._class^.numberstring+'",'+
- tostr(N_PSYM)+',0,0,'+tostr(procinfo.esi_offset)))));
-
- if (porddef(aktprocsym^.definition^.retdef) <> voiddef) then
- procinfo.aktexitcode^.concat(new(pai_stabs,init(strpnew(
- '"'+aktprocsym^.name+':X'+aktprocsym^.definition^.retdef^.numberstring+'",'+
- tostr(N_PSYM)+',0,0,'+tostr(procinfo.retoffset)))));
-
- procinfo.aktexitcode^.concat(new(pai_stabn,init(strpnew('192,0,0,'
- +aktprocsym^.definition^.mangledname))));
-
- procinfo.aktexitcode^.concat(new(pai_stabn,init(strpnew('224,0,0,'
- +lab2str(aktexit2label)))));
- end;
- {$endif * GDB *}
- end;
-
-
- { USES REGISTERS R_A0 AND R_A1 }
- { maximum size of copy is 65535 bytes }
- procedure concatcopy(source,dest : treference;size : longint;delsource : boolean);
-
- var
- ecxpushed : boolean;
- helpsize : longint;
- i : byte;
- reg8,reg32 : tregister;
- swap : boolean;
- hregister : tregister;
- iregister : tregister;
- jregister : tregister;
- hp1 : treference;
- hp2 : treference;
- hl : plabel;
- hl2: plabel;
- begin
- { this should never occur }
- if size > 65535 then
- internalerror(0);
- hregister := getregister32;
- if delsource then
- del_reference(source);
-
- { from 12 bytes movs is being used }
- if (size<=8) or (not(cs_littlesize in aktswitches) and (size<=12)) then
- begin
- helpsize:=size div 4;
- { move a dword x times }
- for i:=1 to helpsize do
- begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(source),hregister)));
- exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,hregister,newreference(dest))));
- inc(source.offset,4);
- inc(dest.offset,4);
- dec(size,4);
- end;
- { move a word }
- if size>1 then
- begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,newreference(source),hregister)));
- exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_W,hregister,newreference(dest))));
- inc(source.offset,2);
- inc(dest.offset,2);
- dec(size,2);
- end;
- { move a single byte }
- if size>0 then
- begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,newreference(source),hregister)));
- exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_B,hregister,newreference(dest))));
- end
-
- end
- else
- begin
- if (usableaddress > 1) then
- begin
- iregister := getaddressreg;
- jregister := getaddressreg;
- end
- else
- if (usableaddress = 1) then
- begin
- iregister := getaddressreg;
- jregister := R_A1;
- end
- else
- begin
- iregister := R_A0;
- jregister := R_A1;
- end;
- { reference for move (An)+,(An)+ }
- reset_reference(hp1);
- hp1.base := iregister; { source register }
- hp1.direction := dir_inc;
- reset_reference(hp2);
- hp2.base := jregister;
- hp2.direction := dir_inc;
- { iregister = source }
- { jregister = destination }
-
-
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(source),iregister)));
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(dest),jregister)));
-
- { double word move only on 68020+ machines }
- { because of possible alignment problems }
- { use fast loop mode }
- if (opt_processors=MC68020) then
- begin
- helpsize := size - size mod 4;
- size := size mod 4;
- exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,helpsize div 4,hregister)));
- getlabel(hl2);
- emitl(A_BRA,hl2);
- getlabel(hl);
- emitl(A_LABEL,hl);
- exprasmlist^.concat(new(pai68k,op_ref_ref(A_MOVE,S_L,newreference(hp1),newreference(hp2))));
- emitl(A_LABEL,hl2);
- exprasmlist^.concat(new(pai_labeled, init_reg(A_DBRA,hl,hregister)));
- if size > 1 then
- begin
- dec(size,2);
- exprasmlist^.concat(new(pai68k,op_ref_ref(A_MOVE,S_W,newreference(hp1), newreference(hp2))));
- end;
- if size = 1 then
- exprasmlist^.concat(new(pai68k,op_ref_ref(A_MOVE,S_B,newreference(hp1), newreference(hp2))));
- end
- else
- begin
- { Fast 68010 loop mode with no possible alignment problems }
- helpsize := size;
- exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,helpsize,hregister)));
- getlabel(hl2);
- emitl(A_BRA,hl2);
- getlabel(hl);
- emitl(A_LABEL,hl);
- exprasmlist^.concat(new(pai68k,op_ref_ref(A_MOVE,S_B,newreference(hp1),newreference(hp2))));
- emitl(A_LABEL,hl2);
- exprasmlist^.concat(new(pai_labeled, init_reg(A_DBRA,hl,hregister)));
- end;
-
- { restore the registers that we have just used olny if they are used! }
- if jregister = R_A1 then
- hp2.base := R_NO;
- if iregister = R_A0 then
- hp1.base := R_NO;
- del_reference(hp1);
- del_reference(hp2);
- end;
-
- { loading SELF-reference again }
- maybe_loada5;
-
- if delsource then
- ungetiftemp(source);
-
- ungetregister32(hregister);
- end;
-
-
- procedure emitloadord2reg(location:Tlocation;orddef:Porddef;
- destreg:Tregister;delloc:boolean);
-
- {A lot smaller and less bug sensitive than the original unfolded loads.}
-
- var tai:pai68k;
- r:Preference;
-
- begin
- case location.loc of
- LOC_REGISTER,LOC_CREGISTER:
- begin
- case orddef^.typ of
- u8bit: begin
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_B,location.register,destreg)));
- exprasmlist^.concat(new(pai68k,op_const_reg(A_ANDI,S_L,$FF,destreg)));
- end;
- s8bit: begin
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_B,location.register,destreg)));
- if (opt_processors <> MC68020) then
- begin
- { byte to word }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_W,destreg)));
- { word to long }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,destreg)));
- end
- else { 68020+ and later only }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXTB,S_L,destreg)));
- end;
- u16bit: begin
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,location.register,destreg)));
- exprasmlist^.concat(new(pai68k,op_const_reg(A_ANDI,S_L,$FFFF,destreg)));
- end;
- s16bit: begin
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_W,location.register,destreg)));
- { word to long }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,destreg)));
- end;
- u32bit:
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,location.register,destreg)));
- s32bit:
- exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,location.register,destreg)));
- end;
- if delloc then
- ungetregister(location.register);
- end;
- LOC_REFERENCE:
- begin
- r:=newreference(location.reference);
- case orddef^.typ of
- u8bit: begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,r,destreg)));
- exprasmlist^.concat(new(pai68k,op_const_reg(A_ANDI,S_L,$FF,destreg)));
- end;
- s8bit: begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,r,destreg)));
- if (opt_processors <> MC68020) then
- begin
- { byte to word }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_W,destreg)));
- { word to long }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,destreg)));
- end
- else { 68020+ and later only }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXTB,S_L,destreg)));
- end;
- u16bit: begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,r,destreg)));
- exprasmlist^.concat(new(pai68k,op_const_reg(A_ANDI,S_L,$ffff,destreg)));
- end;
- s16bit: begin
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_W,r,destreg)));
- { word to long }
- exprasmlist^.concat(new(pai68k,op_reg(A_EXT,S_L,destreg)));
- end;
- u32bit:
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,destreg)));
- s32bit:
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,r,destreg)));
- end;
- if delloc then
- del_reference(location.reference);
- end
- else
- internalerror(6);
- end;
- end;
-
-
- { if necessary A5 is reloaded after a call}
- procedure maybe_loada5;
-
- var
- hp : preference;
- p : pprocinfo;
- i : longint;
-
- begin
- if assigned(procinfo._class) then
- begin
- if lexlevel>2 then
- begin
- new(hp);
- reset_reference(hp^);
- hp^.offset:=procinfo.framepointer_offset;
- hp^.base:=procinfo.framepointer;
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,R_A5)));
- p:=procinfo.parent;
- for i:=3 to lexlevel-1 do
- begin
- new(hp);
- reset_reference(hp^);
- hp^.offset:=p^.framepointer_offset;
- hp^.base:=R_A5;
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,R_A5)));
- p:=p^.parent;
- end;
- new(hp);
- reset_reference(hp^);
- hp^.offset:=p^.ESI_offset;
- hp^.base:=R_A5;
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,R_A5)));
- end
- else
- begin
- new(hp);
- reset_reference(hp^);
- hp^.offset:=procinfo.ESI_offset;
- hp^.base:=procinfo.framepointer;
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,R_A5)));
- end;
- end;
- end;
-
-
- (***********************************************************************)
- (* PROCEDURE FLOATLOAD *)
- (* Description: This routine is to be called each time a location *)
- (* must be set to LOC_FPU and a value loaded into a FPU register. *)
- (* *)
- (* Remark: The routine sets up the register field of LOC_FPU correctly*)
- (***********************************************************************)
-
- procedure floatload(t : tfloattype;const ref : treference; var location:tlocation);
-
- var
- op : tasmop;
- s : topsize;
-
- begin
- { no emulation }
- case t of
- s32real : s := S_S;
- s64real : s := S_Q;
- s80real : s := S_X;
- else
- begin
- Message(cg_f_unknown_float_type);
- end;
- end; { end case }
- location.loc := LOC_FPU;
- if not ((cs_fp_emulation) in aktswitches) then
- begin
- location.fpureg := getfloatreg;
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,s,newreference(ref),location.fpureg)))
- end
- else
- { handle emulation }
- begin
- if t = s32real then
- begin
- location.fpureg := getregister32;
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(ref),location.fpureg)))
- end
- else
- { other floating types are not supported in emulation mode }
- Message(sym_e_type_id_not_defined);
- end;
- end;
-
- { procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
-
- begin
- case t of
- s32real : begin
- op:=A_FSTP;
- s:=S_S;
- end;
- s64real : begin
- op:=A_FSTP;
- s:=S_L;
- end;
- s80real : begin
- op:=A_FSTP;
- s:=S_Q;
- end;
- s64bit : begin
- op:=A_FISTP;
- s:=S_Q;
- end;
- else internalerror(17);
- end;
- end; }
-
-
- { stores an FPU value to memory }
- { location:tlocation used to free up FPU register }
- { ref: destination of storage }
- procedure floatstore(t : tfloattype;var location:tlocation; const ref:treference);
-
- var
- op : tasmop;
- s : topsize;
-
- begin
- if location.loc <> LOC_FPU then
- InternalError(34);
- { no emulation }
- case t of
- s32real : s := S_S;
- s64real : s := S_Q;
- s80real : s := S_X;
- else
- begin
- Message(cg_f_unknown_float_type);
- end;
- end; { end case }
- if not ((cs_fp_emulation) in aktswitches) then
- begin
- { This permits the mixing of emulation and non-emulation routines }
- { only possible for REAL = SINGLE values }
- if not (location.fpureg in [R_FP0..R_FP7]) then
- Begin
- if s = S_S then
- exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,location.fpureg,newreference(ref))))
- else
- internalerror(255);
- end
- else
- exprasmlist^.concat(new(pai68k,op_reg_ref(A_FMOVE,s,location.fpureg,newreference(ref))));
- ungetregister(location.fpureg);
- end
- else
- { handle emulation }
- begin
- if t = s32real then
- begin
- exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,S_L,location.fpureg,newreference(ref))));
- ungetregister32(location.fpureg);
- end
- else
- { other floating types are not supported in emulation mode }
- Message(sym_e_type_id_not_defined);
- end;
- location.fpureg:=R_NO; { no register in LOC_FPU now }
- end;
-
- procedure firstcomplex(p : ptree);
-
- var
- hp : ptree;
-
- begin
- { always calculate boolean AND and OR from left to right }
- if ((p^.treetype=orn) or (p^.treetype=andn)) and
- (p^.left^.resulttype^.deftype=orddef) and
- (porddef(p^.left^.resulttype)^.typ=bool8bit) then
- p^.swaped:=false
- else if (p^.left^.registers32<p^.right^.registers32)
-
- { the following check is appropriate, because all }
- { 4 registers are rarely used and it is thereby }
- { achieved that the extra code is being dropped }
- { by exchanging not commutative operators }
- and (p^.right^.registers32<=4) then
- begin
- hp:=p^.left;
- p^.left:=p^.right;
- p^.right:=hp;
- p^.swaped:=true;
- end
- else p^.swaped:=false;
- end;
-
- procedure secondfuncret(var p : ptree);
-
- var
- hregister : tregister;
-
- begin
- clear_reference(p^.location.reference);
- p^.location.reference.base:=procinfo.framepointer;
- p^.location.reference.offset:=procinfo.retoffset;
- if ret_in_param(procinfo.retdef) then
- begin
- hregister:=getaddressreg;
- exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVEA,S_L,newreference(p^.location.reference),hregister)));
- p^.location.reference.base:=hregister;
- p^.location.reference.offset:=0;
- end;
- end;
-
- procedure codegen_newprocedure;
-
- begin
- aktbreaklabel:=nil;
- aktcontinuelabel:=nil;
- { aktexitlabel:=0; is store in oldaktexitlabel
- so it must not be reset to zero before this storage !}
-
- { the type of this lists isn't important }
- { because the code of this lists is }
- { copied to the code segment }
- procinfo.aktentrycode:=new(paasmoutput,init);
- procinfo.aktexitcode:=new(paasmoutput,init);
- procinfo.aktproccode:=new(paasmoutput,init);
- end;
-
- procedure codegen_doneprocedure;
-
- begin
- dispose(procinfo.aktentrycode,done);
- dispose(procinfo.aktexitcode,done);
- dispose(procinfo.aktproccode,done);
- end;
-
- procedure codegen_newmodule;
-
- begin
- exprasmlist:=new(paasmoutput,init);
- end;
-
- procedure codegen_donemodule;
-
- begin
- dispose(exprasmlist,done);
- dispose(codesegment,done);
- dispose(bsssegment,done);
- dispose(datasegment,done);
- dispose(debuglist,done);
- dispose(externals,done);
- dispose(consts,done);
- end;
-
- end.
- {
- $Log: cga68k.pas,v $
- Revision 1.2.2.7 1998/08/14 12:04:36 carl
- * internalerror 10 bugfix with restore - was allocating two regs
-
- Revision 1.2.2.6 1998/08/13 18:20:21 florian
- * no call to exit is done, if the PalmOS is used
-
- Revision 1.2.2.5 1998/08/13 17:41:22 florian
- + some stuff for the PalmOS added
-
- Revision 1.2.2.4 1998/07/21 12:14:48 carl
- * restore: Would not restore the correct registers if it was a memory
- reference
- * maybe_push: pushes to make sure that at least one data and one
- address register are available
- * loadstring with symbolic name was not being taken care of
-
- Revision 1.2 1998/03/28 23:09:54 florian
- * secondin bugfix (m68k and i386)
- * overflow checking bugfix (m68k and i386) -- pretty useless in
- secondadd, since everything is done using 32-bit
- * loading pointer to routines hopefully fixed (m68k)
- * flags problem with calls to RTL internal routines fixed (still strcmp
- to fix) (m68k)
- * #ELSE was still incorrect (didn't take care of the previous level)
- * problem with filenames in the command line solved
- * problem with mangledname solved
- * linking name problem solved (was case insensitive)
- * double id problem and potential crash solved
- * stop after first error
- * and=>test problem removed
- * correct read for all float types
- * 2 sigsegv fixes and a cosmetic fix for Internal Error
- * push/pop is now correct optimized (=> mov (%esp),reg)
-
- Revision 1.1.1.1 1998/03/25 11:18:13 root
- * Restored version
-
- Revision 1.15 1998/03/22 12:45:38 florian
- * changes of Carl-Eric to m68k target commit:
- - wrong nodes because of the new string cg in intel, I had to create
- this under m68k also ... had to work it out to fix potential alignment
- problems --> this removes the crash of the m68k compiler.
- - added absolute addressing in m68k assembler (required for Amiga startup)
- - fixed alignment problems (because of byte return values, alignment
- would not be always valid) -- is this ok if i change the offset if odd in
- setfirsttemp ?? -- it seems ok...
-
- Revision 1.14 1998/03/10 04:20:37 carl
- * extdebug problems
- - removed loadstring as it is not required for the m68k
-
- Revision 1.13 1998/03/10 01:17:16 peter
- * all files have the same header
- * messages are fully implemented, EXTDEBUG uses Comment()
- + AG... files for the Assembler generation
-
- Revision 1.12 1998/03/09 10:44:35 peter
- + string='', string<>'', string:='', string:=char optimizes (the first 2
- were already in cg68k2)
-
- Revision 1.11 1998/03/06 00:52:03 peter
- * replaced all old messages from errore.msg, only ExtDebug and some
- Comment() calls are left
- * fixed options.pas
-
- Revision 1.10 1998/03/03 04:12:04 carl
- * moved generate routines to this unit
-
- Revision 1.9 1998/03/02 01:48:17 peter
- * renamed target_DOS to target_GO32V1
- + new verbose system, merged old errors and verbose units into one new
- verbose.pas, so errors.pas is obsolete
-
- Revision 1.8 1998/02/13 10:34:45 daniel
- * Made Motorola version compilable.
- * Fixed optimizer
-
- Revision 1.7 1998/02/12 11:49:50 daniel
- Yes! Finally! After three retries, my patch!
-
- Changes:
-
- Complete rewrite of psub.pas.
- Added support for DLL's.
- Compiler requires less memory.
- Platform units for each platform.
-
- Revision 1.6 1998/01/11 03:39:02 carl
- * bugfix of concatcopy , was using wrong reference
- * bugfix of MOVEQ
-
- Revision 1.3 1997/12/09 13:30:05 carl
- + renamed some stuff
-
- Revision 1.2 1997/12/03 13:59:01 carl
- + added emitcall as in i386 version.
-
- Revision 1.1.1.1 1997/11/27 08:32:53 michael
- FPC Compiler CVS start
-
-
- Pre-CVS log:
-
- CEC Carl-Eric Codere
- FK Florian Klaempfl
- PM Pierre Muller
- + feature added
- - removed
- * bug fixed or changed
-
- History:
- 27th september 1997:
- + first version for MC68000 (using v093 template) (CEC)
- 9th october 1997:
- * fixed a bug in push_int as well as other routines which used
- getregister32 while they are not supposed to (because of how
- the allocation of registers work in parser.pas) (CEC)
- * Fixed some bugs in the concatcopy routine, was allocating
- registers which were not supposed to be allocated. (CEC)
-
- }
-