| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 | {    Copyright (c) 1998-2011, 2019 by Florian Klaempfl and Jonas Maebe, Dmitry Boyarintsev    Generate WebAssembly code for math nodes    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 nwasmmat;{$i fpcdefs.inc}interface    uses      node,nmat,ncgmat,ncghlmat;    type      twasmmoddivnode = class(tmoddivnode)         procedure pass_generate_code;override;      end;      twasmshlshrnode = class(tshlshrnode)         procedure pass_generate_code;override;      end;      twasmnotnode = class(tcgnotnode)      protected        procedure second_boolean;override;      end;      twasmunaryminusnode = class(tcgunaryminusnode)        procedure second_integer;override;        procedure second_float;override;      end;implementation    uses      globtype,systems,constexp,      cutils,verbose,globals,compinnr,      symconst,symdef,      aasmbase,aasmcpu,aasmtai,aasmdata,      defutil,      cgbase,cgobj,pass_2,procinfo,      ncon,      cpubase,      hlcgobj,hlcgcpu,cgutils;{*****************************************************************************                             twasmmoddivnode*****************************************************************************}    procedure twasmmoddivnode.pass_generate_code;      var        tmpreg: tregister;        lab: tasmlabel;        ovloc: tlocation;        op: topcg;      begin         secondpass(left);         secondpass(right);         location_reset(location,LOC_REGISTER,left.location.size);         location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);        if nodetype=divn then          begin            thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);            if is_signed(resultdef) then              op:=OP_IDIV            else              op:=OP_DIV;            thlcgwasm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,op,right.resultdef,right.location)          end        else          begin            thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);            thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);            case torddef(resultdef).ordtype of              s64bit:                current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i64_rem_s));              u64bit:                current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i64_rem_u));              s32bit:                current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i32_rem_s));              u32bit:                current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i32_rem_u));              else                internalerror(2022062201);            end;            thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);          end;         thlcgwasm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);         if (cs_check_overflow in current_settings.localswitches) and            is_signed(resultdef) then           begin             { the JVM raises an exception for integer div-iby-zero -> only               overflow in case left is low(inttype) and right is -1 ->               check by adding high(inttype) to left and and'ing with right               -> result is -1 only in case above conditions are fulfilled)             }             tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);             hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,true);             hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_ADD,resultdef,torddef(resultdef).high,right.location.register,tmpreg);             hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true);             hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,left.location.register,tmpreg);             current_asmdata.getjumplabel(lab);             current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));             hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,resultdef,OC_NE,-1,tmpreg,lab);             hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_overflow',[],nil);             hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);             hlcg.a_label(current_asmdata.CurrAsmList,lab);             current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));           end;      end;{*****************************************************************************                             twasmshlshrnode*****************************************************************************}    procedure twasmshlshrnode.pass_generate_code;      var        op : topcg;      begin        secondpass(left);        secondpass(right);        location_reset(location,LOC_REGISTER,left.location.size);        location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);        thlcgwasm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,false);        if nodetype=shln then          op:=OP_SHL        else          op:=OP_SHR;        thlcgwasm(hlcg).a_op_stack(current_asmdata.CurrAsmList,op,resultdef);        thlcgwasm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);      end;{*****************************************************************************                               twasmnotnode*****************************************************************************}    procedure twasmnotnode.second_boolean;      begin        secondpass(left);        if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);        location_reset(location,LOC_REGISTER,left.location.size);        location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);        { perform the NOT operation }        hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,location.register);      end;{*****************************************************************************                            twasmunaryminusnode*****************************************************************************}    procedure twasmunaryminusnode.second_integer;      var        hl: tasmlabel;      begin        secondpass(left);        if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);        if (cs_check_overflow in current_settings.localswitches) then          begin            current_asmdata.getjumplabel(hl);            current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));            hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,resultdef,OC_NE,torddef(resultdef).low.svalue,left.location.register,hl);            hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_overflow',[],nil).resetiftemp;            hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);            hlcg.a_label(current_asmdata.CurrAsmList,hl);            current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));          end;        hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,resultdef,left.location.register,location.register);      end;    procedure twasmunaryminusnode.second_float;      var        opc: tasmop;      begin        secondpass(left);        location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));        location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        if (tfloatdef(left.resultdef).floattype=s32real) then          opc:=a_f32_neg        else          opc:=a_f64_neg;        current_asmdata.CurrAsmList.concat(taicpu.op_none(opc));        thlcgwasm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);      end;begin   cmoddivnode:=twasmmoddivnode;   cshlshrnode:=twasmshlshrnode;   cnotnode:=twasmnotnode;   cunaryminusnode:=twasmunaryminusnode;end.
 |