| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: trap.c,v 1.135 2019/11/21 19:23:58 ad Exp $ */ | | 1 | /* $NetBSD: trap.c,v 1.136 2021/07/19 22:21:36 thorpej Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center, by Charles M. Hannum, and by Ross Harvey. | | 9 | * NASA Ames Research Center, by Charles M. Hannum, and by Ross Harvey. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -77,33 +77,35 @@ | | | @@ -77,33 +77,35 @@ |
77 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | | 77 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
78 | * | | 78 | * |
79 | * Carnegie Mellon requests users of this software to return to | | 79 | * Carnegie Mellon requests users of this software to return to |
80 | * | | 80 | * |
81 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | | 81 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
82 | * School of Computer Science | | 82 | * School of Computer Science |
83 | * Carnegie Mellon University | | 83 | * Carnegie Mellon University |
84 | * Pittsburgh PA 15213-3890 | | 84 | * Pittsburgh PA 15213-3890 |
85 | * | | 85 | * |
86 | * any improvements or extensions that they make and grant Carnegie the | | 86 | * any improvements or extensions that they make and grant Carnegie the |
87 | * rights to redistribute these changes. | | 87 | * rights to redistribute these changes. |
88 | */ | | 88 | */ |
89 | | | 89 | |
| | | 90 | #define __UFETCHSTORE_PRIVATE /* see handle_opdec() */ |
| | | 91 | |
90 | #include "opt_fix_unaligned_vax_fp.h" | | 92 | #include "opt_fix_unaligned_vax_fp.h" |
91 | #include "opt_ddb.h" | | 93 | #include "opt_ddb.h" |
92 | #include "opt_multiprocessor.h" | | 94 | #include "opt_multiprocessor.h" |
93 | | | 95 | |
94 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | | 96 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ |
95 | | | 97 | |
96 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.135 2019/11/21 19:23:58 ad Exp $"); | | 98 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.136 2021/07/19 22:21:36 thorpej Exp $"); |
97 | | | 99 | |
98 | #include <sys/param.h> | | 100 | #include <sys/param.h> |
99 | #include <sys/systm.h> | | 101 | #include <sys/systm.h> |
100 | #include <sys/proc.h> | | 102 | #include <sys/proc.h> |
101 | #include <sys/syscall.h> | | 103 | #include <sys/syscall.h> |
102 | #include <sys/buf.h> | | 104 | #include <sys/buf.h> |
103 | #include <sys/kauth.h> | | 105 | #include <sys/kauth.h> |
104 | #include <sys/kmem.h> | | 106 | #include <sys/kmem.h> |
105 | #include <sys/cpu.h> | | 107 | #include <sys/cpu.h> |
106 | #include <sys/atomic.h> | | 108 | #include <sys/atomic.h> |
107 | | | 109 | |
108 | #include <uvm/uvm_extern.h> | | 110 | #include <uvm/uvm_extern.h> |
109 | | | 111 | |
| @@ -865,109 +867,131 @@ unaligned_fixup(u_long va, u_long opcode | | | @@ -865,109 +867,131 @@ unaligned_fixup(u_long va, u_long opcode |
865 | * | | 867 | * |
866 | * We never allow bad data to be unknowingly used by the user process. | | 868 | * We never allow bad data to be unknowingly used by the user process. |
867 | * That is, if we can't access the address needed to fix up the trap, | | 869 | * That is, if we can't access the address needed to fix up the trap, |
868 | * we cause a SIGSEGV rather than letting the user process go on | | 870 | * we cause a SIGSEGV rather than letting the user process go on |
869 | * without warning. | | 871 | * without warning. |
870 | * | | 872 | * |
871 | * If we're trying to do a fixup, we assume that things | | 873 | * If we're trying to do a fixup, we assume that things |
872 | * will be botched. If everything works out OK, | | 874 | * will be botched. If everything works out OK, |
873 | * unaligned_{load,store}_* clears the signal flag. | | 875 | * unaligned_{load,store}_* clears the signal flag. |
874 | */ | | 876 | */ |
875 | signo = SIGSEGV; | | 877 | signo = SIGSEGV; |
876 | if (dofix && selected_tab->fixable) { | | 878 | if (dofix && selected_tab->fixable) { |
877 | switch (opcode) { | | 879 | switch (opcode) { |
878 | case 0x0c: /* ldwu */ | | 880 | case op_ldwu: |
879 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ | | 881 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ |
880 | unaligned_load_integer(worddata); | | 882 | unaligned_load_integer(worddata); |
881 | break; | | 883 | break; |
882 | | | 884 | |
883 | case 0x0d: /* stw */ | | 885 | case op_stw: |
884 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ | | 886 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ |
885 | unaligned_store_integer(worddata); | | 887 | unaligned_store_integer(worddata); |
886 | break; | | 888 | break; |
887 | | | 889 | |
888 | #ifdef FIX_UNALIGNED_VAX_FP | | 890 | #ifdef FIX_UNALIGNED_VAX_FP |
889 | case 0x20: /* ldf */ | | 891 | case op_ldf: |
890 | unaligned_load_floating(intdata, Ffloat_to_reg); | | 892 | unaligned_load_floating(intdata, Ffloat_to_reg); |
891 | break; | | 893 | break; |
892 | | | 894 | |
893 | case 0x21: /* ldg */ | | 895 | case op_ldg: |
894 | unaligned_load_floating(longdata, Gfloat_reg_cvt); | | 896 | unaligned_load_floating(longdata, Gfloat_reg_cvt); |
895 | break; | | 897 | break; |
896 | #endif | | 898 | #endif |
897 | | | 899 | |
898 | case 0x22: /* lds */ | | 900 | case op_lds: |
899 | unaligned_load_floating(intdata, Sfloat_to_reg); | | 901 | unaligned_load_floating(intdata, Sfloat_to_reg); |
900 | break; | | 902 | break; |
901 | | | 903 | |
902 | case 0x23: /* ldt */ | | 904 | case op_ldt: |
903 | unaligned_load_floating(longdata, Tfloat_reg_cvt); | | 905 | unaligned_load_floating(longdata, Tfloat_reg_cvt); |
904 | break; | | 906 | break; |
905 | | | 907 | |
906 | #ifdef FIX_UNALIGNED_VAX_FP | | 908 | #ifdef FIX_UNALIGNED_VAX_FP |
907 | case 0x24: /* stf */ | | 909 | case op_stf: |
908 | unaligned_store_floating(intdata, reg_to_Ffloat); | | 910 | unaligned_store_floating(intdata, reg_to_Ffloat); |
909 | break; | | 911 | break; |
910 | | | 912 | |
911 | case 0x25: /* stg */ | | 913 | case op_stg: |
912 | unaligned_store_floating(longdata, Gfloat_reg_cvt); | | 914 | unaligned_store_floating(longdata, Gfloat_reg_cvt); |
913 | break; | | 915 | break; |
914 | #endif | | 916 | #endif |
915 | | | 917 | |
916 | case 0x26: /* sts */ | | 918 | case op_sts: |
917 | unaligned_store_floating(intdata, reg_to_Sfloat); | | 919 | unaligned_store_floating(intdata, reg_to_Sfloat); |
918 | break; | | 920 | break; |
919 | | | 921 | |
920 | case 0x27: /* stt */ | | 922 | case op_stt: |
921 | unaligned_store_floating(longdata, Tfloat_reg_cvt); | | 923 | unaligned_store_floating(longdata, Tfloat_reg_cvt); |
922 | break; | | 924 | break; |
923 | | | 925 | |
924 | case 0x28: /* ldl */ | | 926 | case op_ldl: |
925 | unaligned_load_integer(intdata); | | 927 | unaligned_load_integer(intdata); |
926 | break; | | 928 | break; |
927 | | | 929 | |
928 | case 0x29: /* ldq */ | | 930 | case op_ldq: |
929 | unaligned_load_integer(longdata); | | 931 | unaligned_load_integer(longdata); |
930 | break; | | 932 | break; |
931 | | | 933 | |
932 | case 0x2c: /* stl */ | | 934 | case op_stl: |
933 | unaligned_store_integer(intdata); | | 935 | unaligned_store_integer(intdata); |
934 | break; | | 936 | break; |
935 | | | 937 | |
936 | case 0x2d: /* stq */ | | 938 | case op_stq: |
937 | unaligned_store_integer(longdata); | | 939 | unaligned_store_integer(longdata); |
938 | break; | | 940 | break; |
939 | | | 941 | |
940 | #ifdef DIAGNOSTIC | | 942 | #ifdef DIAGNOSTIC |
941 | default: | | 943 | default: |
942 | panic("unaligned_fixup: can't get here"); | | 944 | panic("unaligned_fixup: can't get here"); |
943 | #endif | | 945 | #endif |
944 | } | | 946 | } |
945 | } | | 947 | } |
946 | | | 948 | |
947 | /* | | 949 | /* |
948 | * Force SIGBUS if requested. | | 950 | * Force SIGBUS if requested. |
949 | */ | | 951 | */ |
950 | if (dosigbus) | | 952 | if (dosigbus) |
951 | signo = SIGBUS; | | 953 | signo = SIGBUS; |
952 | | | 954 | |
953 | /* | | 955 | /* |
954 | * Write back USP. | | 956 | * Write back USP. |
955 | */ | | 957 | */ |
956 | alpha_pal_wrusp(l->l_md.md_tf->tf_regs[FRAME_SP]); | | 958 | alpha_pal_wrusp(l->l_md.md_tf->tf_regs[FRAME_SP]); |
957 | | | 959 | |
958 | return (signo); | | 960 | return (signo); |
959 | } | | 961 | } |
960 | | | 962 | |
| | | 963 | static struct evcnt emul_bwx_ldbu = |
| | | 964 | EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "ldbu"); |
| | | 965 | static struct evcnt emul_bwx_ldwu = |
| | | 966 | EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "ldwu"); |
| | | 967 | static struct evcnt emul_bwx_stb = |
| | | 968 | EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "stb"); |
| | | 969 | static struct evcnt emul_bwx_stw = |
| | | 970 | EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "stw"); |
| | | 971 | static struct evcnt emul_bwx_sextb = |
| | | 972 | EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "sextb"); |
| | | 973 | static struct evcnt emul_bwx_sextw = |
| | | 974 | EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "sextw"); |
| | | 975 | |
| | | 976 | EVCNT_ATTACH_STATIC(emul_bwx_ldbu); |
| | | 977 | EVCNT_ATTACH_STATIC(emul_bwx_ldwu); |
| | | 978 | EVCNT_ATTACH_STATIC(emul_bwx_stb); |
| | | 979 | EVCNT_ATTACH_STATIC(emul_bwx_stw); |
| | | 980 | EVCNT_ATTACH_STATIC(emul_bwx_sextb); |
| | | 981 | EVCNT_ATTACH_STATIC(emul_bwx_sextw); |
| | | 982 | |
| | | 983 | #define EMUL_COUNT(ev) atomic_inc_64(&(ev).ev_count) |
| | | 984 | |
961 | /* | | 985 | /* |
962 | * Reserved/unimplemented instruction (opDec fault) handler | | 986 | * Reserved/unimplemented instruction (opDec fault) handler |
963 | * | | 987 | * |
964 | * Argument is the process that caused it. No useful information | | 988 | * Argument is the process that caused it. No useful information |
965 | * is passed to the trap handler other than the fault type. The | | 989 | * is passed to the trap handler other than the fault type. The |
966 | * address of the instruction that caused the fault is 4 less than | | 990 | * address of the instruction that caused the fault is 4 less than |
967 | * the PC stored in the trap frame. | | 991 | * the PC stored in the trap frame. |
968 | * | | 992 | * |
969 | * If the instruction is emulated successfully, this function returns 0. | | 993 | * If the instruction is emulated successfully, this function returns 0. |
970 | * Otherwise, this function returns the signal to deliver to the process, | | 994 | * Otherwise, this function returns the signal to deliver to the process, |
971 | * and fills in *ucodep with the code to be delivered. | | 995 | * and fills in *ucodep with the code to be delivered. |
972 | */ | | 996 | */ |
973 | int | | 997 | int |
| @@ -976,117 +1000,131 @@ handle_opdec(struct lwp *l, u_long *ucod | | | @@ -976,117 +1000,131 @@ handle_opdec(struct lwp *l, u_long *ucod |
976 | alpha_instruction inst; | | 1000 | alpha_instruction inst; |
977 | register_t *regptr, memaddr; | | 1001 | register_t *regptr, memaddr; |
978 | uint64_t inst_pc; | | 1002 | uint64_t inst_pc; |
979 | int sig; | | 1003 | int sig; |
980 | | | 1004 | |
981 | /* | | 1005 | /* |
982 | * Read USP into frame in case it's going to be used or modified. | | 1006 | * Read USP into frame in case it's going to be used or modified. |
983 | * This keeps us from having to check for it in lots of places | | 1007 | * This keeps us from having to check for it in lots of places |
984 | * later. | | 1008 | * later. |
985 | */ | | 1009 | */ |
986 | l->l_md.md_tf->tf_regs[FRAME_SP] = alpha_pal_rdusp(); | | 1010 | l->l_md.md_tf->tf_regs[FRAME_SP] = alpha_pal_rdusp(); |
987 | | | 1011 | |
988 | inst_pc = memaddr = l->l_md.md_tf->tf_regs[FRAME_PC] - 4; | | 1012 | inst_pc = memaddr = l->l_md.md_tf->tf_regs[FRAME_PC] - 4; |
989 | if (copyin((void *)inst_pc, &inst, sizeof (inst)) != 0) { | | 1013 | if (ufetch_int((void *)inst_pc, &inst.bits) != 0) { |
990 | /* | | 1014 | /* |
991 | * really, this should never happen, but in case it | | 1015 | * really, this should never happen, but in case it |
992 | * does we handle it. | | 1016 | * does we handle it. |
993 | */ | | 1017 | */ |
994 | printf("WARNING: handle_opdec() couldn't fetch instruction\n"); | | 1018 | printf("WARNING: handle_opdec() couldn't fetch instruction\n"); |
995 | goto sigsegv; | | 1019 | goto sigsegv; |
996 | } | | 1020 | } |
997 | | | 1021 | |
998 | switch (inst.generic_format.opcode) { | | 1022 | switch (inst.generic_format.opcode) { |
999 | case op_ldbu: | | 1023 | case op_ldbu: |
1000 | case op_ldwu: | | 1024 | case op_ldwu: |
1001 | case op_stw: | | 1025 | case op_stw: |
1002 | case op_stb: | | 1026 | case op_stb: |
1003 | regptr = irp(l, inst.mem_format.rb); | | 1027 | regptr = irp(l, inst.mem_format.rb); |
1004 | if (regptr != NULL) | | 1028 | if (regptr != NULL) |
1005 | memaddr = *regptr; | | 1029 | memaddr = *regptr; |
1006 | else | | 1030 | else |
1007 | memaddr = 0; | | 1031 | memaddr = 0; |
1008 | memaddr += inst.mem_format.displacement; | | 1032 | memaddr += inst.mem_format.displacement; |
1009 | | | 1033 | |
1010 | regptr = irp(l, inst.mem_format.ra); | | 1034 | regptr = irp(l, inst.mem_format.ra); |
1011 | | | 1035 | |
1012 | if (inst.mem_format.opcode == op_ldwu || | | 1036 | if (inst.mem_format.opcode == op_ldwu || |
1013 | inst.mem_format.opcode == op_stw) { | | 1037 | inst.mem_format.opcode == op_stw) { |
1014 | if (memaddr & 0x01) { | | 1038 | if (memaddr & 0x01) { |
| | | 1039 | if (inst.mem_format.opcode == op_ldwu) { |
| | | 1040 | EMUL_COUNT(emul_bwx_ldwu); |
| | | 1041 | } else { |
| | | 1042 | EMUL_COUNT(emul_bwx_stw); |
| | | 1043 | } |
1015 | sig = unaligned_fixup(memaddr, | | 1044 | sig = unaligned_fixup(memaddr, |
1016 | inst.mem_format.opcode, | | 1045 | inst.mem_format.opcode, |
1017 | inst.mem_format.ra, l); | | 1046 | inst.mem_format.ra, l); |
1018 | if (sig) | | 1047 | if (sig) |
1019 | goto unaligned_fixup_sig; | | 1048 | goto unaligned_fixup_sig; |
1020 | break; | | 1049 | break; |
1021 | } | | 1050 | } |
1022 | } | | 1051 | } |
1023 | | | 1052 | |
| | | 1053 | /* |
| | | 1054 | * We know the addresses are aligned, so it's safe to |
| | | 1055 | * use _u{fetch,store}_{8,16}(). Note, these are |
| | | 1056 | * __UFETCHSTORE_PRIVATE, but this is MD code, and |
| | | 1057 | * we know the details of the alpha implementation. |
| | | 1058 | */ |
| | | 1059 | |
1024 | if (inst.mem_format.opcode == op_ldbu) { | | 1060 | if (inst.mem_format.opcode == op_ldbu) { |
1025 | uint8_t b; | | 1061 | uint8_t b; |
1026 | | | 1062 | |
1027 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ | | 1063 | EMUL_COUNT(emul_bwx_ldbu); |
1028 | if (copyin((void *)memaddr, &b, sizeof (b)) != 0) | | 1064 | if (_ufetch_8((void *)memaddr, &b) != 0) |
1029 | goto sigsegv; | | 1065 | goto sigsegv; |
1030 | if (regptr != NULL) | | 1066 | if (regptr != NULL) |
1031 | *regptr = b; | | 1067 | *regptr = b; |
1032 | } else if (inst.mem_format.opcode == op_ldwu) { | | 1068 | } else if (inst.mem_format.opcode == op_ldwu) { |
1033 | uint16_t w; | | 1069 | uint16_t w; |
1034 | | | 1070 | |
1035 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ | | 1071 | EMUL_COUNT(emul_bwx_ldwu); |
1036 | if (copyin((void *)memaddr, &w, sizeof (w)) != 0) | | 1072 | if (_ufetch_16((void *)memaddr, &w) != 0) |
1037 | goto sigsegv; | | 1073 | goto sigsegv; |
1038 | if (regptr != NULL) | | 1074 | if (regptr != NULL) |
1039 | *regptr = w; | | 1075 | *regptr = w; |
1040 | } else if (inst.mem_format.opcode == op_stw) { | | 1076 | } else if (inst.mem_format.opcode == op_stw) { |
1041 | uint16_t w; | | 1077 | uint16_t w; |
1042 | | | 1078 | |
1043 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ | | 1079 | EMUL_COUNT(emul_bwx_stw); |
1044 | w = (regptr != NULL) ? *regptr : 0; | | 1080 | w = (regptr != NULL) ? *regptr : 0; |
1045 | if (copyout(&w, (void *)memaddr, sizeof (w)) != 0) | | 1081 | if (_ustore_16((void *)memaddr, w) != 0) |
1046 | goto sigsegv; | | 1082 | goto sigsegv; |
1047 | } else if (inst.mem_format.opcode == op_stb) { | | 1083 | } else if (inst.mem_format.opcode == op_stb) { |
1048 | uint8_t b; | | 1084 | uint8_t b; |
1049 | | | 1085 | |
1050 | /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ | | 1086 | EMUL_COUNT(emul_bwx_stb); |
1051 | b = (regptr != NULL) ? *regptr : 0; | | 1087 | b = (regptr != NULL) ? *regptr : 0; |
1052 | if (copyout(&b, (void *)memaddr, sizeof (b)) != 0) | | 1088 | if (_ustore_8((void *)memaddr, b) != 0) |
1053 | goto sigsegv; | | 1089 | goto sigsegv; |
1054 | } | | 1090 | } |
1055 | break; | | 1091 | break; |
1056 | | | 1092 | |
1057 | case op_intmisc: | | 1093 | case op_intmisc: |
1058 | if (inst.operate_generic_format.function == op_sextb && | | 1094 | if (inst.operate_generic_format.function == op_sextb && |
1059 | inst.operate_generic_format.ra == 31) { | | 1095 | inst.operate_generic_format.ra == 31) { |
1060 | int8_t b; | | 1096 | int8_t b; |
1061 | | | 1097 | |
| | | 1098 | EMUL_COUNT(emul_bwx_sextb); |
1062 | if (inst.operate_generic_format.is_lit) { | | 1099 | if (inst.operate_generic_format.is_lit) { |
1063 | b = inst.operate_lit_format.literal; | | 1100 | b = inst.operate_lit_format.literal; |
1064 | } else { | | 1101 | } else { |
1065 | if (inst.operate_reg_format.sbz != 0) | | 1102 | if (inst.operate_reg_format.sbz != 0) |
1066 | goto sigill; | | 1103 | goto sigill; |
1067 | regptr = irp(l, inst.operate_reg_format.rb); | | 1104 | regptr = irp(l, inst.operate_reg_format.rb); |
1068 | b = (regptr != NULL) ? *regptr : 0; | | 1105 | b = (regptr != NULL) ? *regptr : 0; |
1069 | } | | 1106 | } |
1070 | | | 1107 | |
1071 | regptr = irp(l, inst.operate_generic_format.rc); | | 1108 | regptr = irp(l, inst.operate_generic_format.rc); |
1072 | if (regptr != NULL) | | 1109 | if (regptr != NULL) |
1073 | *regptr = b; | | 1110 | *regptr = b; |
1074 | break; | | 1111 | break; |
1075 | } | | 1112 | } |
1076 | if (inst.operate_generic_format.function == op_sextw && | | 1113 | if (inst.operate_generic_format.function == op_sextw && |
1077 | inst.operate_generic_format.ra == 31) { | | 1114 | inst.operate_generic_format.ra == 31) { |
1078 | int16_t w; | | 1115 | int16_t w; |
1079 | | | 1116 | |
| | | 1117 | EMUL_COUNT(emul_bwx_sextw); |
1080 | if (inst.operate_generic_format.is_lit) { | | 1118 | if (inst.operate_generic_format.is_lit) { |
1081 | w = inst.operate_lit_format.literal; | | 1119 | w = inst.operate_lit_format.literal; |
1082 | } else { | | 1120 | } else { |
1083 | if (inst.operate_reg_format.sbz != 0) | | 1121 | if (inst.operate_reg_format.sbz != 0) |
1084 | goto sigill; | | 1122 | goto sigill; |
1085 | regptr = irp(l, inst.operate_reg_format.rb); | | 1123 | regptr = irp(l, inst.operate_reg_format.rb); |
1086 | w = (regptr != NULL) ? *regptr : 0; | | 1124 | w = (regptr != NULL) ? *regptr : 0; |
1087 | } | | 1125 | } |
1088 | | | 1126 | |
1089 | regptr = irp(l, inst.operate_generic_format.rc); | | 1127 | regptr = irp(l, inst.operate_generic_format.rc); |
1090 | if (regptr != NULL) | | 1128 | if (regptr != NULL) |
1091 | *regptr = w; | | 1129 | *regptr = w; |
1092 | break; | | 1130 | break; |