History

arm-asm: Add ldrh, ldrsh, ldrsb, strh

Danny Milosavljevic committed 5 years ago

Commit aed49411 parent f44332c3 files · +148 −0Browse files

Unified · Split

3 files
  1. arm-asm.c +142 −0
  2. arm-tok.h +4 −0
  3. tests/arm-asm-testsuite.sh +2 −0
arm-asm.c+142−0
@@ -1116,6 +1116,142 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 1115 unmodified lines
1116 }1116 }
1117}1117}
1118 1118
1119static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)
1120{
1121 Operand ops[3];
1122 int exclam = 0;
1123 int closed_bracket = 0;
1124 int op2_minus = 0;
1125 uint32_t opcode = (1 << 7) | (1 << 4);
1126
1127 /* Note:
1128 The argument syntax is exactly the same as in arm_single_data_transfer_opcode, except that there's no STREX argument form.
1129 The main difference between this function and asm_misc_single_data_transfer_opcode is that the immediate values here must be smaller.
1130 Also, the combination (P=0, W=1) is unpredictable here.
1131 The immediate flag has moved to bit index 22--and its meaning has flipped.
1132 The immediate value itself has been split into two parts: one at bits 11...8, one at bits 3...0
1133 bit 26 (Load/Store instruction) is unset here.
1134 bits 7 and 4 are set here. */
1135
1136 // Here: 0 0 0 P U I W L << 20
1137 // [compare single data transfer: 0 1 I P U B W L << 20]
1138
1139 parse_operand(s1, &ops[0]);
1140 if (ops[0].type == OP_REG32)
1141 opcode |= ENCODE_RD(ops[0].reg);
1142 else {
1143 expect("(destination operand) register");
1144 return;
1145 }
1146 if (tok != ',')
1147 expect("at least two arguments");
1148 else
1149 next(); // skip ','
1150
1151 if (tok != '[')
1152 expect("'['");
1153 else
1154 next(); // skip '['
1155
1156 parse_operand(s1, &ops[1]);
1157 if (ops[1].type == OP_REG32)
1158 opcode |= ENCODE_RN(ops[1].reg);
1159 else {
1160 expect("(first source operand) register");
1161 return;
1162 }
1163 if (tok == ']') {
1164 next();
1165 closed_bracket = 1;
1166 // exclam = 1; // implicit in hardware; don't do it in software
1167 }
1168 if (tok == ',') {
1169 next(); // skip ','
1170 if (tok == '-') {
1171 op2_minus = 1;
1172 next();
1173 }
1174 parse_operand(s1, &ops[2]);
1175 } else {
1176 // end of input expression in brackets--assume 0 offset
1177 ops[2].type = OP_IM8;
1178 ops[2].e.v = 0;
1179 opcode |= 1 << 24; // add offset before transfer
1180 }
1181 if (!closed_bracket) {
1182 if (tok != ']')
1183 expect("']'");
1184 else
1185 next(); // skip ']'
1186 opcode |= 1 << 24; // add offset before transfer
1187 if (tok == '!') {
1188 exclam = 1;
1189 next(); // skip '!'
1190 }
1191 }
1192
1193 if (exclam) {
1194 if ((opcode & (1 << 24)) == 0) {
1195 tcc_error("result of '%s' would be unpredictable here", get_tok_str(token, NULL));
1196 return;
1197 }
1198 opcode |= 1 << 21; // write offset back into register
1199 }
1200
1201 if (ops[2].type == OP_IM32 || ops[2].type == OP_IM8 || ops[2].type == OP_IM8N) {
1202 int v = ops[2].e.v;
1203 if (op2_minus)
1204 tcc_error("minus before '#' not supported for immediate values");
1205 if (v >= 0) {
1206 opcode |= 1 << 23; // up
1207 if (v >= 0x100)
1208 tcc_error("offset out of range for '%s'", get_tok_str(token, NULL));
1209 else {
1210 // bits 11...8: immediate hi nibble
1211 // bits 3...0: immediate lo nibble
1212 opcode |= (v & 0xF0) << 4;
1213 opcode |= v & 0xF;
1214 }
1215 } else { // down
1216 if (v <= -0x100)
1217 tcc_error("offset out of range for '%s'", get_tok_str(token, NULL));
1218 else {
1219 v = -v;
1220 // bits 11...8: immediate hi nibble
1221 // bits 3...0: immediate lo nibble
1222 opcode |= (v & 0xF0) << 4;
1223 opcode |= v & 0xF;
1224 }
1225 }
1226 opcode |= 1 << 22; // not ENCODE_IMMEDIATE_FLAG;
1227 } else if (ops[2].type == OP_REG32) {
1228 if (!op2_minus)
1229 opcode |= 1 << 23; // up
1230 opcode |= ops[2].reg;
1231 } else
1232 expect("register");
1233
1234 switch (ARM_INSTRUCTION_GROUP(token)) {
1235 case TOK_ASM_ldrsheq:
1236 opcode |= 1 << 5; // halfword, not byte
1237 /* fallthrough */
1238 case TOK_ASM_ldrsbeq:
1239 opcode |= 1 << 6; // sign extend
1240 opcode |= 1 << 20; // L
1241 asm_emit_opcode(token, opcode);
1242 break;
1243 case TOK_ASM_ldrheq:
1244 opcode |= 1 << 5; // halfword, not byte
1245 opcode |= 1 << 20; // L
1246 asm_emit_opcode(token, opcode);
1247 break;
1248 case TOK_ASM_strheq:
1249 opcode |= 1 << 5; // halfword, not byte
1250 asm_emit_opcode(token, opcode);
1251 break;
1252 }
1253}
1254
1119/* Note: almost dupe of encbranch in arm-gen.c */1255/* Note: almost dupe of encbranch in arm-gen.c */
1120static uint32_t encbranchoffset(int pos, int addr, int fail)1256static uint32_t encbranchoffset(int pos, int addr, int fail)
1121{1257{
@@ -1232,6 +1368,12 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 110 unmodified lines
1232 case TOK_ASM_strexbeq:1368 case TOK_ASM_strexbeq:
1233 return asm_single_data_transfer_opcode(s1, token);1369 return asm_single_data_transfer_opcode(s1, token);
1234 1370
1371 case TOK_ASM_ldrheq:
1372 case TOK_ASM_ldrsheq:
1373 case TOK_ASM_ldrsbeq:
1374 case TOK_ASM_strheq:
1375 return asm_misc_single_data_transfer_opcode(s1, token);
1376
1235 case TOK_ASM_andeq:1377 case TOK_ASM_andeq:
1236 case TOK_ASM_eoreq:1378 case TOK_ASM_eoreq:
1237 case TOK_ASM_subeq:1379 case TOK_ASM_subeq:
arm-tok.h+4−0
@@ -97,6 +97,10 @@ · 96 unmodified lines
97 DEF_ASM_CONDED(ldrexb)97 DEF_ASM_CONDED(ldrexb)
98 DEF_ASM_CONDED(strex)98 DEF_ASM_CONDED(strex)
99 DEF_ASM_CONDED(strexb)99 DEF_ASM_CONDED(strexb)
100 DEF_ASM_CONDED(ldrh)
101 DEF_ASM_CONDED(ldrsh)
102 DEF_ASM_CONDED(ldrsb)
103 DEF_ASM_CONDED(strh)
100 104
101 DEF_ASM_CONDED(stmda)105 DEF_ASM_CONDED(stmda)
102 DEF_ASM_CONDED(ldmda)106 DEF_ASM_CONDED(ldmda)
tests/arm-asm-testsuite.sh+2−0
@@ -65,6 +65,8 @@ do · 64 unmodified lines
65 "r2, r3, [r4]" \65 "r2, r3, [r4]" \
66 "r2, [r3, #4]" \66 "r2, [r3, #4]" \
67 "r2, [r3, #-4]" \67 "r2, [r3, #-4]" \
68 "r2, [r3, #0x45]" \
69 "r2, [r3, #-0x45]" \
68 "r2, r3, #4" \70 "r2, r3, #4" \
69 "r2, r3, #-4" \71 "r2, r3, #-4" \
70 "r2, #4" \72 "r2, #4" \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t