Revision 6ea83fed target-mips/op.c

b/target-mips/op.c
2 2
 *  MIPS emulation micro-operations for qemu.
3 3
 * 
4 4
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5
 *  Copyright (c) 2006 Marius Groeger (FPU operations)
5 6
 *
6 7
 * This library is free software; you can redistribute it and/or
7 8
 * modify it under the terms of the GNU Lesser General Public
......
149 150
#include "op_template.c"
150 151
#undef TN
151 152

  
153
#ifdef MIPS_USES_FPU
154

  
155
#define SFREG 0
156
#define DFREG 0
157
#include "fop_template.c"
158
#undef SFREG
159
#undef DFREG
160
#define SFREG 1
161
#include "fop_template.c"
162
#undef SFREG
163
#define SFREG 2
164
#define DFREG 2
165
#include "fop_template.c"
166
#undef SFREG
167
#undef DFREG
168
#define SFREG 3
169
#include "fop_template.c"
170
#undef SFREG
171
#define SFREG 4
172
#define DFREG 4
173
#include "fop_template.c"
174
#undef SFREG
175
#undef DFREG
176
#define SFREG 5
177
#include "fop_template.c"
178
#undef SFREG
179
#define SFREG 6
180
#define DFREG 6
181
#include "fop_template.c"
182
#undef SFREG
183
#undef DFREG
184
#define SFREG 7
185
#include "fop_template.c"
186
#undef SFREG
187
#define SFREG 8
188
#define DFREG 8
189
#include "fop_template.c"
190
#undef SFREG
191
#undef DFREG
192
#define SFREG 9
193
#include "fop_template.c"
194
#undef SFREG
195
#define SFREG 10
196
#define DFREG 10
197
#include "fop_template.c"
198
#undef SFREG
199
#undef DFREG
200
#define SFREG 11
201
#include "fop_template.c"
202
#undef SFREG
203
#define SFREG 12
204
#define DFREG 12
205
#include "fop_template.c"
206
#undef SFREG
207
#undef DFREG
208
#define SFREG 13
209
#include "fop_template.c"
210
#undef SFREG
211
#define SFREG 14
212
#define DFREG 14
213
#include "fop_template.c"
214
#undef SFREG
215
#undef DFREG
216
#define SFREG 15
217
#include "fop_template.c"
218
#undef SFREG
219
#define SFREG 16
220
#define DFREG 16
221
#include "fop_template.c"
222
#undef SFREG
223
#undef DFREG
224
#define SFREG 17
225
#include "fop_template.c"
226
#undef SFREG
227
#define SFREG 18
228
#define DFREG 18
229
#include "fop_template.c"
230
#undef SFREG
231
#undef DFREG
232
#define SFREG 19
233
#include "fop_template.c"
234
#undef SFREG
235
#define SFREG 20
236
#define DFREG 20
237
#include "fop_template.c"
238
#undef SFREG
239
#undef DFREG
240
#define SFREG 21
241
#include "fop_template.c"
242
#undef SFREG
243
#define SFREG 22
244
#define DFREG 22
245
#include "fop_template.c"
246
#undef SFREG
247
#undef DFREG
248
#define SFREG 23
249
#include "fop_template.c"
250
#undef SFREG
251
#define SFREG 24
252
#define DFREG 24
253
#include "fop_template.c"
254
#undef SFREG
255
#undef DFREG
256
#define SFREG 25
257
#include "fop_template.c"
258
#undef SFREG
259
#define SFREG 26
260
#define DFREG 26
261
#include "fop_template.c"
262
#undef SFREG
263
#undef DFREG
264
#define SFREG 27
265
#include "fop_template.c"
266
#undef SFREG
267
#define SFREG 28
268
#define DFREG 28
269
#include "fop_template.c"
270
#undef SFREG
271
#undef DFREG
272
#define SFREG 29
273
#include "fop_template.c"
274
#undef SFREG
275
#define SFREG 30
276
#define DFREG 30
277
#include "fop_template.c"
278
#undef SFREG
279
#undef DFREG
280
#define SFREG 31
281
#include "fop_template.c"
282
#undef SFREG
283

  
284
#define FTN
285
#include "fop_template.c"
286
#undef FTN
287

  
288
#endif
289

  
152 290
void op_dup_T0 (void)
153 291
{
154 292
    T2 = T0;
......
562 700
    RETURN();
563 701
}
564 702

  
703
#ifdef MIPS_USES_FPU
704

  
705
#if 0
706
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
707
#else
708
# define DEBUG_FPU_STATE() do { } while(0)
709
#endif
710

  
711
void op_cp1_enabled(void)
712
{
713
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
714
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
715
    }
716
    RETURN();
717
}
718

  
719
/* CP1 functions */
720
void op_cfc1 (void)
721
{
722
    if (T1 == 0) {
723
        T0 = env->fcr0;
724
    }
725
    else {
726
        /* fetch fcr31, masking unused bits */
727
        T0 = env->fcr31 & 0x0183FFFF;
728
    }
729
    DEBUG_FPU_STATE();
730
    RETURN();
731
}
732

  
733
/* convert MIPS rounding mode in FCR31 to IEEE library */
734
unsigned int ieee_rm[] = { 
735
    float_round_nearest_even,
736
    float_round_to_zero,
737
    float_round_up,
738
    float_round_down
739
};
740

  
741
#define RESTORE_ROUNDING_MODE \
742
    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
743

  
744
void op_ctc1 (void)
745
{
746
    if (T1 == 0) {
747
        /* XXX should this throw an exception?
748
         * don't write to FCR0.
749
         * env->fcr0 = T0; 
750
         */
751
    }
752
    else {
753
        /* store new fcr31, masking unused bits */  
754
        env->fcr31 = T0 & 0x0183FFFF;
755

  
756
        /* set rounding mode */
757
        RESTORE_ROUNDING_MODE;
758

  
759
#ifndef CONFIG_SOFTFLOAT
760
        /* no floating point exception for native float */
761
        SET_FP_ENABLE(env->fcr31, 0);
762
#endif
763
    }
764
    DEBUG_FPU_STATE();
765
    RETURN();
766
}
767

  
768
void op_mfc1 (void)
769
{
770
    T0 = WT0;
771
    DEBUG_FPU_STATE();
772
    RETURN();
773
}
774

  
775
void op_mtc1 (void)
776
{
777
    WT0 = T0;
778
    DEBUG_FPU_STATE();
779
    RETURN();
780
}
781

  
782
/* Float support.
783
   Single precition routines have a "s" suffix, double precision a
784
   "d" suffix.  */
785

  
786
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
787

  
788
FLOAT_OP(cvtd, w)
789
{
790
    FDT2 = int32_to_float64(WT0, &env->fp_status);
791
    DEBUG_FPU_STATE();
792
    RETURN();
793
}
794
FLOAT_OP(cvts, w)
795
{
796
    FST2 = int32_to_float32(WT0, &env->fp_status);
797
    DEBUG_FPU_STATE();
798
    RETURN();
799
}
800
FLOAT_OP(cvtw, s)
801
{
802
    WT2 = float32_to_int32(FST0, &env->fp_status);
803
    DEBUG_FPU_STATE();
804
    RETURN();
805
}
806
FLOAT_OP(cvtw, d)
807
{
808
    WT2 = float64_to_int32(FDT0, &env->fp_status);
809
    DEBUG_FPU_STATE();
810
    RETURN();
811
}
812

  
813
FLOAT_OP(roundw, d)
814
{
815
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
816
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
817
    RESTORE_ROUNDING_MODE;
818

  
819
    DEBUG_FPU_STATE();
820
    RETURN();
821
}
822
FLOAT_OP(roundw, s)
823
{
824
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
825
    WT2 = float32_round_to_int(FST0, &env->fp_status);
826
    RESTORE_ROUNDING_MODE;
827
    DEBUG_FPU_STATE();
828
    RETURN();
829
}
830

  
831
FLOAT_OP(truncw, d)
832
{
833
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
834
    DEBUG_FPU_STATE();
835
    RETURN();
836
}
837
FLOAT_OP(truncw, s)
838
{
839
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
840
    DEBUG_FPU_STATE();
841
    RETURN();
842
}
843

  
844
FLOAT_OP(ceilw, d)
845
{
846
    set_float_rounding_mode(float_round_up, &env->fp_status);
847
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
848
    RESTORE_ROUNDING_MODE;
849

  
850
    DEBUG_FPU_STATE();
851
    RETURN();
852
}
853
FLOAT_OP(ceilw, s)
854
{
855
    set_float_rounding_mode(float_round_up, &env->fp_status);
856
    WT2 = float32_round_to_int(FST0, &env->fp_status);
857
    RESTORE_ROUNDING_MODE;
858
    DEBUG_FPU_STATE();
859
    RETURN();
860
}
861

  
862
FLOAT_OP(floorw, d)
863
{
864
    set_float_rounding_mode(float_round_down, &env->fp_status);
865
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
866
    RESTORE_ROUNDING_MODE;
867

  
868
    DEBUG_FPU_STATE();
869
    RETURN();
870
}
871
FLOAT_OP(floorw, s)
872
{
873
    set_float_rounding_mode(float_round_down, &env->fp_status);
874
    WT2 = float32_round_to_int(FST0, &env->fp_status);
875
    RESTORE_ROUNDING_MODE;
876
    DEBUG_FPU_STATE();
877
    RETURN();
878
}
879

  
880
/* binary operations */
881
#define FLOAT_BINOP(name) \
882
FLOAT_OP(name, d)         \
883
{                         \
884
    FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
885
    DEBUG_FPU_STATE();    \
886
}                         \
887
FLOAT_OP(name, s)         \
888
{                         \
889
    FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
890
    DEBUG_FPU_STATE();    \
891
}
892
FLOAT_BINOP(add)
893
FLOAT_BINOP(sub)
894
FLOAT_BINOP(mul)
895
FLOAT_BINOP(div)
896
#undef FLOAT_BINOP
897

  
898
/* unary operations, modifying fp status  */
899
#define FLOAT_UNOP(name)  \
900
FLOAT_OP(name, d)         \
901
{                         \
902
    FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
903
    DEBUG_FPU_STATE();    \
904
}                         \
905
FLOAT_OP(name, s)         \
906
{                         \
907
    FST2 = float32_ ## name(FST0, &env->fp_status);   \
908
    DEBUG_FPU_STATE();    \
909
}
910
FLOAT_UNOP(sqrt)
911
#undef FLOAT_UNOP
912

  
913
/* unary operations, not modifying fp status  */
914
#define FLOAT_UNOP(name)  \
915
FLOAT_OP(name, d)         \
916
{                         \
917
    FDT2 = float64_ ## name(FDT0);   \
918
    DEBUG_FPU_STATE();    \
919
}                         \
920
FLOAT_OP(name, s)         \
921
{                         \
922
    FST2 = float32_ ## name(FST0);   \
923
    DEBUG_FPU_STATE();    \
924
}
925
FLOAT_UNOP(abs)
926
FLOAT_UNOP(chs)
927
#undef FLOAT_UNOP
928

  
929
FLOAT_OP(mov, d)
930
{
931
    FDT2 = FDT0;
932
    DEBUG_FPU_STATE();
933
    RETURN();
934
}
935
FLOAT_OP(mov, s)
936
{
937
    FST2 = FST0;
938
    DEBUG_FPU_STATE();
939
    RETURN();
940
}
941

  
942
#ifdef CONFIG_SOFTFLOAT
943
#define clear_invalid() do {                                \
944
    int flags = get_float_exception_flags(&env->fp_status); \
945
    flags &= ~float_flag_invalid;                           \
946
    set_float_exception_flags(flags, &env->fp_status);      \
947
} while(0)
948
#else
949
#define clear_invalid() do { } while(0)
950
#endif
951

  
952
extern void dump_fpu_s(CPUState *env);
953

  
954
#define FOP_COND(fmt, op, sig, cond)           \
955
void op_cmp_ ## fmt ## _ ## op (void)          \
956
{                                              \
957
    if (cond)                                  \
958
        SET_FP_COND(env->fcr31);               \
959
    else                                       \
960
        CLEAR_FP_COND(env->fcr31);             \
961
    if (!sig)                                  \
962
        clear_invalid();                       \
963
    /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
964
    DEBUG_FPU_STATE();                         \
965
    RETURN();                                  \
966
}
967

  
968
flag float64_is_unordered(float64 a, float64 b STATUS_PARAM)
969
{
970
    extern flag float64_is_nan( float64 a );
971
    if (float64_is_nan(a) || float64_is_nan(b)) {
972
        float_raise(float_flag_invalid, status);
973
        return 1;
974
    }
975
    else {
976
        return 0;
977
    }
978
}
979

  
980
FOP_COND(d, f,   0,                                                      0) 
981
FOP_COND(d, un,  0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
982
FOP_COND(d, eq,  0,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
983
FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
984
FOP_COND(d, olt, 0,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
985
FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
986
FOP_COND(d, ole, 0,                                                      float64_le(FDT0, FDT1, &env->fp_status))
987
FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
988
/* NOTE: the comma operator will make "cond" to eval to false,
989
 * but float*_is_unordered() is still called
990
 */
991
FOP_COND(d, sf,  1,                                                      (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
992
FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
993
FOP_COND(d, seq, 1,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
994
FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
995
FOP_COND(d, lt,  1,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
996
FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
997
FOP_COND(d, le,  1,                                                      float64_le(FDT0, FDT1, &env->fp_status))
998
FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
999

  
1000
flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1001
{
1002
    extern flag float32_is_nan( float32 a );
1003
    if (float32_is_nan(a) || float32_is_nan(b)) {
1004
        float_raise(float_flag_invalid, status);
1005
        return 1;
1006
    }
1007
    else {
1008
        return 0;
1009
    }
1010
}
1011

  
1012
/* NOTE: the comma operator will make "cond" to eval to false,
1013
 * but float*_is_unordered() is still called
1014
 */
1015
FOP_COND(s, f,   0,                                                      0) 
1016
FOP_COND(s, un,  0, float32_is_unordered(FST1, FST0, &env->fp_status))
1017
FOP_COND(s, eq,  0,                                                      float32_eq(FST0, FST1, &env->fp_status))
1018
FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1019
FOP_COND(s, olt, 0,                                                      float32_lt(FST0, FST1, &env->fp_status))
1020
FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1021
FOP_COND(s, ole, 0,                                                      float32_le(FST0, FST1, &env->fp_status))
1022
FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1023
/* NOTE: the comma operator will make "cond" to eval to false,
1024
 * but float*_is_unordered() is still called
1025
 */
1026
FOP_COND(s, sf,  1,                                                      (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1027
FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1028
FOP_COND(s, seq, 1,                                                      float32_eq(FST0, FST1, &env->fp_status))
1029
FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1030
FOP_COND(s, lt,  1,                                                      float32_lt(FST0, FST1, &env->fp_status))
1031
FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1032
FOP_COND(s, le,  1,                                                      float32_le(FST0, FST1, &env->fp_status))
1033
FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1034

  
1035
void op_bc1f (void)
1036
{
1037
    T0 = ! IS_FP_COND_SET(env->fcr31);
1038
    DEBUG_FPU_STATE();
1039
    RETURN();
1040
}
1041

  
1042
void op_bc1t (void)
1043
{
1044
    T0 = IS_FP_COND_SET(env->fcr31);
1045
    DEBUG_FPU_STATE();
1046
    RETURN();
1047
}
1048
#endif /* MIPS_USES_FPU */
1049

  
565 1050
#if defined(MIPS_USES_R4K_TLB)
566 1051
void op_tlbwi (void)
567 1052
{

Also available in: Unified diff