| @@ -221,6 +221,112 @@ static void asm_binary_opcode(TCCState* s1, int token) · 220 unmodified lines |
| 221 | } | 221 | } |
| 222 | } | 222 | } |
| 223 | | 223 | |
| | 224 | /* caller: Add funct3, funct7 into opcode */ |
| | 225 | static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2) |
| | 226 | { |
| | 227 | if (rd->type != OP_REG) { |
| | 228 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| | 229 | return; |
| | 230 | } |
| | 231 | if (rs1->type != OP_REG) { |
| | 232 | tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL)); |
| | 233 | return; |
| | 234 | } |
| | 235 | if (rs2->type != OP_REG) { |
| | 236 | tcc_error("'%s': Expected second source operand that is a register or immediate", get_tok_str(token, NULL)); |
| | 237 | return; |
| | 238 | } |
| | 239 | /* R-type instruction: |
| | 240 | 31...25 funct7 |
| | 241 | 24...20 rs2 |
| | 242 | 19...15 rs1 |
| | 243 | 14...12 funct3 |
| | 244 | 11...7 rd |
| | 245 | 6...0 opcode */ |
| | 246 | gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg)); |
| | 247 | } |
| | 248 | |
| | 249 | /* caller: Add funct3 into opcode */ |
| | 250 | static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2) |
| | 251 | { |
| | 252 | if (rd->type != OP_REG) { |
| | 253 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| | 254 | return; |
| | 255 | } |
| | 256 | if (rs1->type != OP_REG) { |
| | 257 | tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL)); |
| | 258 | return; |
| | 259 | } |
| | 260 | if (rs2->type != OP_IM12S) { |
| | 261 | tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(token, NULL)); |
| | 262 | return; |
| | 263 | } |
| | 264 | /* I-type instruction: |
| | 265 | 31...20 imm[11:0] |
| | 266 | 19...15 rs1 |
| | 267 | 14...12 funct3 |
| | 268 | 11...7 rd |
| | 269 | 6...0 opcode */ |
| | 270 | |
| | 271 | gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20)); |
| | 272 | } |
| | 273 | |
| | 274 | static void asm_shift_opcode(TCCState *s1, int token) |
| | 275 | { |
| | 276 | Operand ops[3]; |
| | 277 | parse_operand(s1, &ops[0]); |
| | 278 | if (tok == ',') |
| | 279 | next(); |
| | 280 | else |
| | 281 | expect("','"); |
| | 282 | parse_operand(s1, &ops[1]); |
| | 283 | if (tok == ',') |
| | 284 | next(); |
| | 285 | else |
| | 286 | expect("','"); |
| | 287 | parse_operand(s1, &ops[2]); |
| | 288 | |
| | 289 | switch (token) { |
| | 290 | case TOK_ASM_sll: |
| | 291 | asm_emit_r(token, (0xC << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); |
| | 292 | return; |
| | 293 | case TOK_ASM_slli: |
| | 294 | asm_emit_i(token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); |
| | 295 | return; |
| | 296 | case TOK_ASM_srl: |
| | 297 | asm_emit_r(token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]); |
| | 298 | return; |
| | 299 | case TOK_ASM_srli: |
| | 300 | asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); |
| | 301 | return; |
| | 302 | case TOK_ASM_sra: |
| | 303 | asm_emit_r(token, (0xC << 2) | 3 | (5 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]); |
| | 304 | return; |
| | 305 | case TOK_ASM_srai: |
| | 306 | asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12) | (16 << 26), &ops[0], &ops[1], &ops[2]); |
| | 307 | return; |
| | 308 | case TOK_ASM_sllw: |
| | 309 | asm_emit_r(token, (0xE << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); |
| | 310 | return; |
| | 311 | case TOK_ASM_slliw: |
| | 312 | asm_emit_i(token, (6 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); |
| | 313 | return; |
| | 314 | case TOK_ASM_srlw: |
| | 315 | asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); |
| | 316 | return; |
| | 317 | case TOK_ASM_srliw: |
| | 318 | asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); |
| | 319 | return; |
| | 320 | case TOK_ASM_sraw: |
| | 321 | asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); |
| | 322 | return; |
| | 323 | case TOK_ASM_sraiw: |
| | 324 | asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); |
| | 325 | return; |
| | 326 | default: |
| | 327 | expect("shift instruction"); |
| | 328 | } |
| | 329 | } |
| 224 | | 330 | |
| 225 | ST_FUNC void asm_opcode(TCCState *s1, int token) | 331 | ST_FUNC void asm_opcode(TCCState *s1, int token) |
| 226 | { | 332 | { |
| @@ -252,6 +358,27 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 25 unmodified lines |
| 252 | asm_binary_opcode(s1, token); | 358 | asm_binary_opcode(s1, token); |
| 253 | return; | 359 | return; |
| 254 | | 360 | |
| | 361 | case TOK_ASM_sll: |
| | 362 | case TOK_ASM_slli: |
| | 363 | case TOK_ASM_srl: |
| | 364 | case TOK_ASM_srli: |
| | 365 | case TOK_ASM_sra: |
| | 366 | case TOK_ASM_srai: |
| | 367 | case TOK_ASM_sllw: |
| | 368 | case TOK_ASM_slld: |
| | 369 | case TOK_ASM_slliw: |
| | 370 | case TOK_ASM_sllid: |
| | 371 | case TOK_ASM_srlw: |
| | 372 | case TOK_ASM_srld: |
| | 373 | case TOK_ASM_srliw: |
| | 374 | case TOK_ASM_srlid: |
| | 375 | case TOK_ASM_sraw: |
| | 376 | case TOK_ASM_srad: |
| | 377 | case TOK_ASM_sraiw: |
| | 378 | case TOK_ASM_sraid: |
| | 379 | asm_shift_opcode(s1, token); |
| | 380 | return; |
| | 381 | |
| 255 | default: | 382 | default: |
| 256 | expect("known instruction"); | 383 | expect("known instruction"); |
| 257 | } | 384 | } |