9
9
#include "runtime.h"
10
10
11
11
#define CPSR 14
12
- #define FLAGS_N (1 << 31)
13
- #define FLAGS_Z (1 << 30)
14
- #define FLAGS_C (1 << 29)
15
- #define FLAGS_V (1 << 28)
12
+ #define FLAGS_N (1U << 31)
13
+ #define FLAGS_Z (1U << 30)
14
+ #define FLAGS_C (1U << 29)
15
+ #define FLAGS_V (1U << 28)
16
16
17
17
void runtime·abort (void );
18
18
void math·sqrtC (uint64 , uint64 * );
@@ -86,12 +86,24 @@ fstatus(bool nan, int32 cmp)
86
86
return FLAGS_C ;
87
87
}
88
88
89
+ // conditions array record the required CPSR cond field for the
90
+ // first 5 pairs of conditional execution opcodes
91
+ // higher 4 bits are must set, lower 4 bits are must clear
92
+ static const uint8 conditions [10 /2 ] = {
93
+ [0 /2 ] = (FLAGS_Z >> 24 ) | 0 , // 0: EQ (Z set), 1: NE (Z clear)
94
+ [2 /2 ] = (FLAGS_C >> 24 ) | 0 , // 2: CS/HS (C set), 3: CC/LO (C clear)
95
+ [4 /2 ] = (FLAGS_N >> 24 ) | 0 , // 4: MI (N set), 5: PL (N clear)
96
+ [6 /2 ] = (FLAGS_V >> 24 ) | 0 , // 6: VS (V set), 7: VC (V clear)
97
+ [8 /2 ] = (FLAGS_C >> 24 ) |
98
+ (FLAGS_Z >> 28 ), // 8: HI (C set and Z clear), 9: LS (C clear and Z set)
99
+ };
100
+
89
101
// returns number of words that the fp instruction
90
102
// is occupying, 0 if next instruction isn't float.
91
103
static uint32
92
104
stepflt (uint32 * pc , uint32 * regs )
93
105
{
94
- uint32 i , regd , regm , regn ;
106
+ uint32 i , opc , regd , regm , regn , cpsr ;
95
107
int32 delta ;
96
108
uint32 * addr ;
97
109
uint64 uval ;
@@ -102,8 +114,49 @@ stepflt(uint32 *pc, uint32 *regs)
102
114
i = * pc ;
103
115
104
116
if (trace )
105
- runtime·printf ("stepflt %p %x\n" , pc , i );
117
+ runtime·printf ("stepflt %p %x (cpsr %x)\n" , pc , i , regs [CPSR ] >> 28 );
118
+
119
+ opc = i >> 28 ;
120
+ if (opc == 14 ) // common case first
121
+ goto execute ;
122
+ cpsr = regs [CPSR ] >> 28 ;
123
+ switch (opc ) {
124
+ case 0 : case 1 : case 2 : case 3 : case 4 :
125
+ case 5 : case 6 : case 7 : case 8 : case 9 :
126
+ if (((cpsr & (conditions [opc /2 ] >> 4 )) == (conditions [opc /2 ] >> 4 )) &&
127
+ ((cpsr & (conditions [opc /2 ] & 0xf )) == 0 )) {
128
+ if (opc & 1 ) return 1 ;
129
+ } else {
130
+ if (!(opc & 1 )) return 1 ;
131
+ }
132
+ break ;
133
+ case 10 : // GE (N == V)
134
+ case 11 : // LT (N != V)
135
+ if ((cpsr & (FLAGS_N >> 28 )) == (cpsr & (FLAGS_V >> 28 ))) {
136
+ if (opc & 1 ) return 1 ;
137
+ } else {
138
+ if (!(opc & 1 )) return 1 ;
139
+ }
140
+ break ;
141
+ case 12 : // GT (N == V and Z == 0)
142
+ case 13 : // LE (N != V or Z == 1)
143
+ if ((cpsr & (FLAGS_N >> 28 )) == (cpsr & (FLAGS_V >> 28 )) &&
144
+ (cpsr & (FLAGS_Z >> 28 )) == 0 ) {
145
+ if (opc & 1 ) return 1 ;
146
+ } else {
147
+ if (!(opc & 1 )) return 1 ;
148
+ }
149
+ break ;
150
+ case 14 : // AL
151
+ break ;
152
+ case 15 : // shouldn't happen
153
+ return 0 ;
154
+ }
155
+ if (trace )
156
+ runtime·printf ("conditional %x (cpsr %x) pass\n" , opc , cpsr );
157
+ i = (0xeU << 28 ) | (i & 0xfffffff );
106
158
159
+ execute :
107
160
// special cases
108
161
if ((i & 0xfffff000 ) == 0xe59fb000 ) {
109
162
// load r11 from pc-relative address.
0 commit comments