diff options
Diffstat (limited to 'compiler/m68k/ra68k.pas')
-rwxr-xr-x | compiler/m68k/ra68k.pas | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/compiler/m68k/ra68k.pas b/compiler/m68k/ra68k.pas new file mode 100755 index 0000000000..3b7c24dc8d --- /dev/null +++ b/compiler/m68k/ra68k.pas @@ -0,0 +1,363 @@ +{ + Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman + + Handles the common 68k assembler reader routines + + 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 ra68k; + +{$i fpcdefs.inc} + + interface + + uses + aasmbase,aasmtai,aasmcpu, + cpubase,rautils,cclasses; + + type + Tm68kOperand=class(TOperand) + end; + + Tm68kInstruction=class(TInstruction) + opsize : topsize; + function ConcatInstruction(p : taasmoutput):tai;override; + function ConcatLabeledInstr(p : taasmoutput):tai; + end; + + implementation + + uses + verbose,cgbase; + +{***************************************************************************** + TM68kInstruction +*****************************************************************************} + + function TM68kInstruction.ConcatInstruction(p : taasmoutput):tai; + var + fits : boolean; + begin + result:=nil; + fits := FALSE; + { setup specific opcodetions for first pass } + + { Setup special operands } + { Convert to general form as to conform to the m68k opcode table } + if (opcode = A_ADDA) or (opcode = A_ADDI) + then opcode := A_ADD + else + { CMPM excluded because of GAS v1.34 BUG } + if (opcode = A_CMPA) or + (opcode = A_CMPI) then + opcode := A_CMP + else + if opcode = A_EORI then + opcode := A_EOR + else + if opcode = A_MOVEA then + opcode := A_MOVE + else + if opcode = A_ORI then + opcode := A_OR + else + if (opcode = A_SUBA) or (opcode = A_SUBI) then + opcode := A_SUB; + + { Setup operand types } + +(* + in opcode <> A_MOVEM then + begin + + while not(fits) do + begin + { set the opcodetion cache, if the opcodetion } + { occurs the first time } + if (it[i].i=opcode) and (ins_cache[opcode]=-1) then + ins_cache[opcode]:=i; + + if (it[i].i=opcode) and (instr.ops=it[i].ops) then + begin + { first fit } + case instr.ops of + 0 : begin + fits:=true; + break; + end; + 1 : + begin + if (optyp1 and it[i].o1)<>0 then + begin + fits:=true; + break; + end; + end; + 2 : if ((optyp1 and it[i].o1)<>0) and + ((optyp2 and it[i].o2)<>0) then + begin + fits:=true; + break; + end + 3 : if ((optyp1 and it[i].o1)<>0) and + ((optyp2 and it[i].o2)<>0) and + ((optyp3 and it[i].o3)<>0) then + begin + fits:=true; + break; + end; + end; { end case } + end; { endif } + if it[i].i=A_NONE then + begin + { NO MATCH! } + Message(asmr_e_invalid_combination_opcode_and_operand); + exit; + end; + inc(i); + end; { end while } + *) + fits:=TRUE; + + { We add the opcode to the opcode linked list } + if fits then + begin + case ops of + 0: + if opsize <> S_NO then + result:=(taicpu.op_none(opcode,opsize)) + else + result:=(taicpu.op_none(opcode,S_NO)); + 1: begin + case operands[1].opr.typ of + OPR_SYMBOL: + begin + result:=(taicpu.op_sym_ofs(opcode, + opsize, operands[1].opr.symbol,operands[1].opr.symofs)); + end; + OPR_CONSTANT: + begin + result:=(taicpu.op_const(opcode, + opsize, operands[1].opr.val)); + end; + OPR_REGISTER: + result:=(taicpu.op_reg(opcode,opsize,operands[1].opr.reg)); + OPR_REFERENCE: + if opsize <> S_NO then + begin + result:=(taicpu.op_ref(opcode, + opsize,operands[1].opr.ref)); + end + else + begin + { special jmp and call case with } + { symbolic references. } + if opcode in [A_BSR,A_JMP,A_JSR,A_BRA,A_PEA] then + begin + result:=(taicpu.op_ref(opcode, + S_NO,operands[1].opr.ref)); + end + else + Message(asmr_e_invalid_opcode_and_operand); + end; + OPR_NONE: + Message(asmr_e_invalid_opcode_and_operand); + else + begin + Message(asmr_e_invalid_opcode_and_operand); + end; + end; + end; + 2: begin + { source } + case operands[1].opr.typ of + { reg,reg } + { reg,ref } + OPR_REGISTER: + begin + case operands[2].opr.typ of + OPR_REGISTER: + begin + result:=(taicpu.op_reg_reg(opcode, + opsize,operands[1].opr.reg,operands[2].opr.reg)); + end; + OPR_REFERENCE: + result:=(taicpu.op_reg_ref(opcode, + opsize,operands[1].opr.reg,operands[2].opr.ref)); + else { else case } + begin + Message(asmr_e_invalid_opcode_and_operand); + end; + end; { end second operand case for OPR_REGISTER } + end; + { regset, ref } + OPR_regset: + begin + case operands[2].opr.typ of + OPR_REFERENCE : + result:=(taicpu.op_regset_ref(opcode, + opsize,operands[1].opr.regset,operands[2].opr.ref)); + else + begin + Message(asmr_e_invalid_opcode_and_operand); + end; + end; { end second operand case for OPR_regset } + end; + + { const,reg } + { const,const } + { const,ref } + OPR_CONSTANT: + case operands[2].opr.typ of + { constant, constant does not have a specific size. } + OPR_CONSTANT: + result:=(taicpu.op_const_const(opcode, + S_NO,operands[1].opr.val,operands[2].opr.val)); + OPR_REFERENCE: + begin + result:=(taicpu.op_const_ref(opcode, + opsize,operands[1].opr.val, + operands[2].opr.ref)) + end; + OPR_REGISTER: + begin + result:=(taicpu.op_const_reg(opcode, + opsize,operands[1].opr.val, + operands[2].opr.reg)) + end; + else + begin + Message(asmr_e_invalid_opcode_and_operand); + end; + end; { end second operand case for OPR_CONSTANT } + { ref,reg } + { ref,ref } + OPR_REFERENCE: + case operands[2].opr.typ of + OPR_REGISTER: + begin + result:=(taicpu.op_ref_reg(opcode, + opsize,operands[1].opr.ref, + operands[2].opr.reg)); + end; + OPR_regset: + begin + result:=(taicpu.op_ref_regset(opcode, + opsize,operands[1].opr.ref, + operands[2].opr.regset)); + end; + OPR_REFERENCE: { special opcodes } + result:=(taicpu.op_ref_ref(opcode, + opsize,operands[1].opr.ref, + operands[2].opr.ref)); + else + begin + Message(asmr_e_invalid_opcode_and_operand); + end; + end; { end second operand case for OPR_REFERENCE } + OPR_SYMBOL: case operands[2].opr.typ of + OPR_REFERENCE: + begin + result:=(taicpu.op_sym_ofs_ref(opcode, + opsize,operands[1].opr.symbol,operands[1].opr.symofs, + operands[2].opr.ref)) + end; + OPR_REGISTER: + begin + result:=(taicpu.op_sym_ofs_reg(opcode, + opsize,operands[1].opr.symbol,operands[1].opr.symofs, + operands[2].opr.reg)) + end; + else + begin + Message(asmr_e_invalid_opcode_and_operand); + end; + end; { end second operand case for OPR_SYMBOL } + else + begin + Message(asmr_e_invalid_opcode_and_operand); + end; + end; { end first operand case } + end; + 3: begin + if (opcode = A_DIVSL) or (opcode = A_DIVUL) or (opcode = A_MULU) + or (opcode = A_MULS) or (opcode = A_DIVS) or (opcode = A_DIVU) then + begin + if (operands[1].opr.typ <> OPR_REGISTER) + or (operands[2].opr.typ <> OPR_REGISTER) + or (operands[3].opr.typ <> OPR_REGISTER) then + begin + Message(asmr_e_invalid_opcode_and_operand); + end + else + begin + result:=(taicpu. op_reg_reg_reg(opcode,opsize, + operands[1].opr.reg,operands[2].opr.reg,operands[3].opr.reg)); + end; + end + else + Message(asmr_e_invalid_opcode_and_operand); + end; + end; { end case } + end; + if assigned(result) then + p.concat(result); + end; + + + function TM68kInstruction.ConcatLabeledInstr(p : taasmoutput):tai; + begin + if ((opcode >= A_BCC) and (opcode <= A_BVS)) or + (opcode = A_BRA) or (opcode = A_BSR) or + (opcode = A_JMP) or (opcode = A_JSR) or + ((opcode >= A_FBEQ) and (opcode <= A_FBNGLE)) then + begin + if ops > 2 then + Message(asmr_e_invalid_opcode_and_operand) + else if operands[1].opr.typ <> OPR_SYMBOL then + Message(asmr_e_invalid_opcode_and_operand) + else if (operands[1].opr.typ = OPR_SYMBOL) and + (ops = 1) then + if assigned(operands[1].opr.symbol) and + (operands[1].opr.symofs=0) then + result:=taicpu.op_sym(opcode,S_NO, + operands[1].opr.symbol) + else + Message(asmr_e_invalid_opcode_and_operand); + end + else if ((opcode >= A_DBCC) and (opcode <= A_DBF)) + or ((opcode >= A_FDBEQ) and (opcode <= A_FDBNGLE)) then + begin + if (ops<>2) or + (operands[1].opr.typ <> OPR_REGISTER) or + (operands[2].opr.typ <> OPR_SYMBOL) or + (operands[2].opr.symofs <> 0) then + Message(asmr_e_invalid_opcode_and_operand) + else + result:=taicpu.op_reg_sym(opcode,opsize,operands[1].opr.reg, + operands[2].opr.symbol); + end + else + Message(asmr_e_invalid_opcode_and_operand); + if assigned(result) then + p.concat(result); + end; + + + + +end. |