diff options
Diffstat (limited to 'closures/compiler/mips/aasmcpu.pas')
-rw-r--r-- | closures/compiler/mips/aasmcpu.pas | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/closures/compiler/mips/aasmcpu.pas b/closures/compiler/mips/aasmcpu.pas new file mode 100644 index 0000000000..263d2a242b --- /dev/null +++ b/closures/compiler/mips/aasmcpu.pas @@ -0,0 +1,449 @@ +{ + Copyright (c) 1999-2009 by Mazen Neifer and David Zhang + + Contains the assembler object for the MIPSEL + + 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 aasmcpu; + +{$i fpcdefs.inc} + +interface + +uses + cclasses, + globtype, globals, verbose, + aasmbase, aasmsym, aasmtai, + cgbase, cgutils, cpubase, cpuinfo; + +const + { "mov reg,reg" source operand number } + O_MOV_SOURCE = 0; + { "mov reg,reg" source operand number } + O_MOV_DEST = 1; + +type + taicpu = class(tai_cpu_abstract_sym) + delayslot_annulled: boolean; { conditinal opcode with ,a } + constructor op_none(op: tasmop); + + constructor op_reg(op: tasmop; _op1: tregister); + constructor op_const(op: tasmop; _op1: longint); + constructor op_ref(op: tasmop; const _op1: treference); + + constructor op_reg_reg(op: tasmop; _op1, _op2: tregister); + constructor op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference); + constructor op_reg_const(op: tasmop; _op1: tregister; _op2: longint); + + constructor op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister); + + constructor op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference); + constructor op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint); + + { this is for Jmp instructions } + constructor op_sym(op: tasmop; _op1: tasmsymbol); + constructor op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol); + constructor op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol); + constructor op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint); + + { register allocation } + function is_same_reg_move(regtype: Tregistertype): boolean; override; + + { register spilling code } + function spilling_get_operation_type(opnr: longint): topertype; override; + end; + + tai_align = class(tai_align_abstract) + { nothing to add } + end; + + procedure InitAsm; + procedure DoneAsm; + + function spilling_create_load(const ref: treference; r: tregister): taicpu; + function spilling_create_store(r: tregister; const ref: treference): taicpu; + +implementation + +{***************************************************************************** + taicpu Constructors +*****************************************************************************} + + + +constructor taicpu.op_none(op: tasmop); +begin + inherited Create(op); +end; + + +constructor taicpu.op_reg(op: tasmop; _op1: tregister); +begin + inherited Create(op); + ops := 1; + loadreg(0, _op1); +end; + + +constructor taicpu.op_ref(op: tasmop; const _op1: treference); +begin + inherited Create(op); + ops := 1; + loadref(0, _op1); +end; + + +constructor taicpu.op_const(op: tasmop; _op1: longint); +begin + inherited Create(op); + ops := 1; + loadconst(0, _op1); +end; + + +constructor taicpu.op_reg_reg(op: tasmop; _op1, _op2: tregister); +begin + inherited Create(op); + ops := 2; + loadreg(0, _op1); + loadreg(1, _op2); +end; + +constructor taicpu.op_reg_const(op: tasmop; _op1: tregister; _op2: longint); +begin + inherited Create(op); + ops := 2; + loadreg(0, _op1); + loadconst(1, _op2); +end; + + +constructor taicpu.op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference); +begin + inherited Create(op); + ops := 2; + loadreg(0, _op1); + loadref(1, _op2); +end; + + +constructor taicpu.op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister); +begin + inherited Create(op); + ops := 3; + loadreg(0, _op1); + loadreg(1, _op2); + loadreg(2, _op3); +end; + + +constructor taicpu.op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference); + begin + inherited create(op); + ops := 3; + loadreg(0, _op1); + loadreg(1, _op2); + loadref(2, _op3); +end; + +constructor taicpu.op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint); + begin + inherited create(op); + ops := 3; + loadreg(0, _op1); + loadreg(1, _op2); + loadconst(2, _op3); +end; + + + +constructor taicpu.op_sym(op: tasmop; _op1: tasmsymbol); +begin + inherited Create(op); + is_jmp := op in [A_J, A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, + A_BLTUI, A_BLEUI, A_BGTUI, A_BGEUI, + A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, + A_BLTU, A_BLEU, A_BGTU, A_BGEU + ]; + + ops := 1; + loadsymbol(0, _op1, 0); +end; + +constructor taicpu.op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol); +begin + inherited create(op); + is_jmp := op in [A_J, + A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI, + A_BGTUI, A_BGEUI, + A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU]; + ops := 3; + loadreg(0, _op1); + loadreg(1, _op2); + loadsymbol(2, _op3, 0); +end; + +constructor taicpu.op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol); +begin + inherited create(op); + is_jmp := op in [A_J, + A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI, + A_BGTUI, A_BGEUI, + A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU, A_BGTZ]; + ops := 2; + loadreg(0, _op1); + loadsymbol(1, _op2, 0); +end; + +constructor taicpu.op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint); +begin + inherited Create(op); + ops := 1; + loadsymbol(0, _op1, _op1ofs); +end; + + +function taicpu.is_same_reg_move(regtype: Tregistertype): boolean; +begin + Result := ( + ((opcode = A_MOVE) and (regtype = R_INTREGISTER)) or + ((regtype = R_FPUREGISTER) and (opcode in [A_MOV_S, A_MOV_D])) + ) and + (oper[0]^.reg = oper[1]^.reg); +end; + + + function taicpu.spilling_get_operation_type(opnr: longint): topertype; + type + op_write_set_type = set of TAsmOp; + const + op_write_set: op_write_set_type = + [A_NEG, + A_NEGU, + A_LI, + A_DLI, + A_LA, + A_MOVE, + A_LB, + A_LBU, + A_LH, + A_LHU, + A_LW, + A_LWU, + A_LWL, + A_LWR, + A_LD, + A_LDL, + A_LDR, + A_LL, + A_LLD, + A_ADDI, + A_DADDI, + A_ADDIU, + A_DADDIU, + A_SLTI, + A_SLTIU, + A_ANDI, + A_ORI, + A_XORI, + A_LUI, + A_DNEG, + A_DNEGU, + A_ADD, + A_DADD, + A_ADDU, + A_DADDU, + A_SUB, + A_DSUB, + A_SUBU, + A_DSUBU, + A_SLT, + A_SLTU, + A_AND, + A_OR, + A_XOR, + A_NOR, + A_MUL, + A_MULO, + A_MULOU, + A_DMUL, + A_DMULO, + A_DMULOU, + A_DIV, + A_DIVU, + A_DDIV, + A_DDIVU, + A_REM, + A_REMU, + A_DREM, + A_DREMU, + A_MULT, + A_DMULT, + A_MULTU, + A_DMULTU, + A_MFHI, + A_MFLO, + A_MULTG, + A_DMULTG, + A_MULTUG, + A_DMULTUG, + A_DIVG, + A_DDIVG, + A_DIVUG, + A_DDIVUG, + A_MODG, + A_DMODG, + A_MODUG, + A_DMODUG, + + A_SLL, + A_SRL, + A_SRA, + A_SLLV, + A_SRLV, + A_SRAV, + A_DSLL, + A_DSRL, + A_DSRA, + A_DSLLV, + A_DSRLV, + A_DSRAV, + A_DSLL32, + A_DSRL32, + A_DSRA32, + A_LWC1, + A_LDC1, + + + A_ADD_S, + A_ADD_D, + A_SUB_S, + A_SUB_D, + A_MUL_S, + A_MUL_D, + A_DIV_S, + A_DIV_D, + A_ABS_S, + A_ABS_D, + A_NEG_S, + A_NEG_D, + A_SQRT_S, + A_SQRT_D, + A_MOV_S, + A_MOV_D, + A_CVT_S_D, + A_CVT_S_W, + A_CVT_S_L, + A_CVT_D_S, + A_CVT_D_W, + A_CVT_D_L, + A_CVT_W_S, + A_CVT_W_D, + A_CVT_L_S, + A_CVT_L_D, + A_ROUND_W_S, + A_ROUND_W_D, + A_ROUND_L_S, + A_ROUND_L_D, + A_TRUNC_W_S, + A_TRUNC_W_D, + A_TRUNC_L_S, + A_TRUNC_L_D, + A_CEIL_W_S, + A_CEIL_W_D, + A_CEIL_L_S, + A_CEIL_L_D, + A_FLOOR_W_S, + A_FLOOR_W_D, + A_FLOOR_L_S, + A_FLOOR_L_D, + A_SEQ, + A_SGE, + A_SGEU, + A_SGT, + A_SGTU, + A_SLE, + A_SLEU, + A_SNE]; + + begin + result := operand_read; + if opcode in op_write_set then + if opnr = 0 then + result := operand_write; + end; + + + function spilling_create_load(const ref: treference; r: tregister): taicpu; + begin + case getregtype(r) of + R_INTREGISTER : + result:=taicpu.op_reg_ref(A_LW,r,ref); + R_FPUREGISTER : + begin + case getsubreg(r) of + R_SUBFS : + result:=taicpu.op_reg_ref(A_LWC1,r,ref); + R_SUBFD : + result:=taicpu.op_reg_ref(A_LDC1,r,ref); + else + internalerror(200401042); + end; + end + else + internalerror(200401041); + end; + end; + + + function spilling_create_store(r: tregister; const ref: treference): taicpu; + begin + case getregtype(r) of + R_INTREGISTER : + result:=taicpu.op_reg_ref(A_SW,r,ref); + R_FPUREGISTER : + begin + case getsubreg(r) of + R_SUBFS : + result:=taicpu.op_reg_ref(A_SWC1,r,ref); + R_SUBFD : + result:=taicpu.op_reg_ref(A_SDC1,r,ref); + else + internalerror(200401042); + end; + end + else + internalerror(200401041); + end; + end; + + +procedure InitAsm; + begin + end; + + +procedure DoneAsm; + begin + end; + + +begin + cai_cpu := taicpu; + cai_align := tai_align; +end. |